P7399 [COCI2020-2021#5] Po
题目 :P7399 [COCI2020-2021#5] Po
题面
你会获得一个长度为
思路
我们可以数形结合,把整个序列想象成一个二位平面,如图(此篇以第3个样例为例讲解):
题面“变换”的意思就是把区间
这里区间 (可以自己推导出来,方便理解)。
做到这里,有经验的朋友可以发现此题和P5019 铺设道路的区间修改很类似,只是有些不同。我们可以把序列看作一座座山,在山的另一边如果有与之相同的高度,就可以在一次变换中将这两边的此高度的区间变换。
例如可以把样例中的区间
区间
那么如何实现呢?这就可以用到单调栈了(详情请见P5788 【模板】单调栈)。
由于山的上坡是上升序列,下坡是下降序列,我们就可以把上坡中的每一个高度存在一个栈里,等到枚举到下坡的时候再一一比较,比当前高度高的栈顶元素直接弹出。如果弹到最后发现栈顶元素比当前高度小或者栈空了,就说明上坡时没有与之对应的区间可以在同一变换中变换,那么就不得不另用一次变换使当前区间变换(如果等于,就是符合要求,是可以在同一次变换中变换的)。
code:
#include<bits/stdc++.h>
using namespace std;
int n,sol,x;
stack<int>s;
int main()
{
scanf("%d",&n);
while(n--)
{
scanf("%d",&x);
while(!s.empty()&&s.top()>x) s.pop();//比当前高度高的直接弹出,注意要保证栈里有元素,否则可能会出错
if(!s.empty()&&s.top()==x) continue;//符合要求直接进入下一层循环
if(x) sol++,s.push(x);//注意,由于原序列是全0序列,所以当高度为0时是不需要变换的,也就不需要压入栈中
}
printf("%d",sol);
return 0;
}
画功不好,见谅QWQ