【CCPC】2022绵阳站 G. Let Them Eat Cake | 模拟

148 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情

【CCPC】2022绵阳站 G. Let Them Eat Cake | 模拟

题目链接

Problem - G - Codeforces

题目

image.png

题目大意

给定长度为 nn 的数组 a1,a2,...,ana_1,a_2,...,a_n,每次操作流程如下:

  • 对于数组中的每一个元素 ii,判断所有与 ii 相邻的元素中是否存在比它大的元素,若存在,给 ii 打上标记。
  • 把数组中所有带有标记的数字移除,剩余的数字按原顺序紧密排列。

直到数组中仅包括一个元素为止,求操作次数。

思路

容易发现每次操作后除了比左右两个相邻数字都大的数字外,其他数字都会被删除。那么整个数组中的元素至少会减少 n2\lfloor\frac{n}{2}\rfloor,直接模拟即可,不会超出时限。

在数组中删除元素比较难以实现,虽然可以使用链表或者使用 vector,但都需要增加一些讨论,不必要地提升编码难度。我们可以把“删除满足条件的数字”变成“保留不满足条件的数字”。

因为在本题中元素的下标并不重要,我们可以直接忽略他们的原位置,新开一个数组记录我们想要保留的元素。在遍历过程中直接将不满足条件的数字添加到保留数组的末尾即可。

为了省去将保留数组复制回原数组的开销,可以用滚动数组。

代码

#include <iostream>
#include <algorithm>
#include <math.h>
#include <stdio.h>
#include <map>
#include <vector>
#include <queue>
using namespace std;
using LL=long long;
const int N=500001;
const LL mod=1000000007;
//const LL mod=998244353;
int n,a[2][N];
LL solve()
{
	scanf("%d",&n);
	for (int i=1;i<=n;++i) scanf("%d",&a[0][i]);
	int ans=0;
	for (int o=1,m=0;n>1;m=0,o=!o)
	{
		ans++;
		a[!o][0]=a[!o][n+1]=0;
		for (int i=1;i<=n;++i)
			if (a[!o][i]>a[!o][i-1]&&a[!o][i]>a[!o][i+1]) a[o][++m]=a[!o][i];
		n=m;
	}
	printf("%d\n",ans);
        return 0;
}
int main()
{
	int T=1;
	while (T--) solve();
	return 0;
}