http://codeforces.com/problemset/problem/319/B
一串数列,每一个值如果大于相邻右一位的值的话,那么就可以把右边这个值“吃掉”(右一位消失,原来的值不变),问需要吃多少次才能到达无法再吃的状态。
利用栈。遍历一遍数组,处理每个值的时候,如果栈顶的元素小于该值,那么将其弹出,知道栈顶元素大于该值或者栈为空,栈内的每个元素记录下一个属性:他是在第几次被“吃掉”,进栈的新元素的被吃次数就是它弹出去的元素中的属性的最大值+1,如果没有弹任何值则为1;如果栈空,则值为0;
保持整个队列递减
策略如下
如果一个数进去没有弹出数,则这个数肯定是第一场就被消掉的
如果一个数进去弹出了一些数,则该数被吃掉的场次等于它弹走的所有数中最大的被吃掉的场次序号+1,因为,这个数肯定是在它弹掉的数之后被吃掉的(它被弹完后的队列中最后面一个数吃掉)
如果一个数进去弹出了所有的数,则这个数被吃掉的场次为0
当然,一开始是要找到从第一个开始的单调子串中的最后一个数作为这个队列的第一个数,并且场次为0
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define MS(a) memset(a,0,sizeof(a)) #define MP make_pair #define PB push_back const int INF = 0x3f3f3f3f; const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } ////////////////////////////////////////////////////////////////////////// const int maxn = 1e5+10; int n,a[maxn]; struct node{ int x,y; }que[maxn]; int main(){ cin >> n; for(int i=1; i<=n; i++) a[i] = read(); int i=2; while(a[i]>a[i-1]) i++; int tail = 0, ans = 0, mx=0; que[tail].x = a[i-1], que[tail++].y = 0; for( ; i<=n; i++){ if(a[i] < que[tail-1].x){ que[tail].x = a[i], que[tail++].y = 1; ans = max(ans,que[tail-1].y); continue; } mx = 0; while(tail>0 && a[i]>que[tail-1].x) mx=max(mx,que[tail-1].y),tail--; que[tail].x = a[i]; if(tail==0) que[tail++].y=0; else que[tail++].y=mx+1; ans = max(ans,que[tail-1].y); } cout << ans << endl; return 0; }
Codeforces 319B. Psychos in a Line【单调栈】
原文:http://www.cnblogs.com/yxg123123/p/7252903.html