开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情
【CCPC】2022绵阳站 G. Let Them Eat Cake | 模拟
题目链接
题目
题目大意
给定长度为 的数组 ,每次操作流程如下:
- 对于数组中的每一个元素 ,判断所有与 相邻的元素中是否存在比它大的元素,若存在,给 打上标记。
- 把数组中所有带有标记的数字移除,剩余的数字按原顺序紧密排列。
直到数组中仅包括一个元素为止,求操作次数。
思路
容易发现每次操作后除了比左右两个相邻数字都大的数字外,其他数字都会被删除。那么整个数组中的元素至少会减少 ,直接模拟即可,不会超出时限。
在数组中删除元素比较难以实现,虽然可以使用链表或者使用 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;
}