1. 程式人生 > >Codeforces 547B Mike and Feet(單調棧)

Codeforces 547B Mike and Feet(單調棧)

urn otherwise ios 遍歷 n-1 bsp fine ons 什麽是

題目鏈接:http://codeforces.com/problemset/problem/547/B

題目大意:
有一個長度為n的序列,序列有長度為1...n的連續子序列,一個連續子序列裏面最小的值稱作這個子序列的子序列的strength,
要求出每種長度的連續子序列的最大的strength。
解題思路:
可以用棧求出每個點的l[i],表示值小於當前位置並且在左側的最接近這個點的位置。
同理可以求出r[i],表示值小於當前位置並且在右側側的最接近這個點的位置。
求l[i]過程如下:
stack s // initially empty
for i = 1 to n
while s is not empty and a[s.top()] >= a[i]

do s.pop()
if s is empty
then l[i] = 0
otherwise
l[i] = s.top()
s.push(i)
接下來,我們遍歷每個位置i,令len=r[i]-l[i]-1,則ans[len]=min(a[i],ans[len])
可以理解為在r[i]-1~l[i]+1這塊長度為len的區間上,最小的就是a[i],所以ans[len]與a[i]比較。
最後還要從len=n-1~1遍歷,令ans[len]=max(ans[len],a[len+1])。
為什麽要這麽做?
因為不這樣做,如1 2 3 2 1這組樣例,只能求出ans[1]、ans[3]、ans[5],像ans[2]、ans[4]都是空的。
這樣做的意義就是如果ans[len]為空,則把ans[len+1]的值給它。
為什麽是ans[len+1]的值,首先ans[len]>=ans[len+1],假設我們有一個長度為len+1的只有x~y的區間,min=2,則a[len+1]=2,
假設a[len]會大於a[len+1],那麽必定存在x+1~y或者x~y-1的區間且min>2,但是如果ans[len-1]為空則說明沒有這樣的區間
所以取ans[len]=ans[len+1]。

代碼

 1 #include<bits/stdc++.h>
 2 #define lc(a) (a<<1)
 3 #define
rc(a) (a<<1|1) 4 #define MID(a,b) ((a+b)>>1) 5 #define fin(name) freopen(name,"r",stdin) 6 #define fout(name) freopen(name,"w",stdout) 7 #define clr(arr,val) memset(arr,val,sizeof(arr)) 8 #define _for(i,start,end) for(int i=start;i<=end;i++) 9 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0); 10 using namespace std; 11 typedef long long LL; 12 const int N=2e5+5; 13 const int INF=0x3f3f3f3f; 14 const double eps=1e-10; 15 16 int l[N],r[N],a[N],ans[N]; 17 stack<int>sk; 18 19 int main(){ 20 FAST_IO; 21 int n; 22 cin>>n; 23 for(int i=1;i<=n;i++){ 24 cin>>a[i]; 25 } 26 for(int i=1;i<=n;i++){ 27 while(!sk.empty()&&a[sk.top()]>=a[i]) 28 sk.pop(); 29 if(!sk.empty()) 30 l[i]=sk.top(); 31 else 32 l[i]=0; 33 sk.push(i); 34 } 35 while(!sk.empty()) sk.pop(); 36 for(int i=n;i>=1;i--){ 37 while(!sk.empty()&&a[sk.top()]>=a[i]) 38 sk.pop(); 39 if(!sk.empty()) 40 r[i]=sk.top(); 41 else 42 r[i]=n+1; 43 sk.push(i); 44 } 45 for(int i=1;i<=n;i++){ 46 int len=r[i]-l[i]-1; 47 ans[len]=max(a[i],ans[len]); 48 } 49 for(int i=n-1;i>=1;i--){ 50 ans[i]=max(ans[i],ans[i+1]); 51 } 52 for(int i=1;i<=n;i++){ 53 cout<<ans[i]<<" "; 54 } 55 cout<<endl; 56 return 0; 57 }

Codeforces 547B Mike and Feet(單調棧)