1. 程式人生 > >Codeforces 319B. Psychos in a Line【單調棧】

Codeforces 319B. Psychos in a Line【單調棧】

push_back 找到 cnblogs air inline nod pre type ==

題目鏈接:

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【單調棧】