Codeforces Round #305 (Div. 1) B. Mike and Feet(單調棧)
阿新 • • 發佈:2019-01-25
題意:給定一個長度為n(n<=2e5)的陣列,分別求出長度為(1~n)的所有區間的最小數的最大值。
思路:ans[i]表示長度為i區間的答案,我們可以知道如果i<j,那麼ans[i]>=ans[j],所以可以用長度大的區間答案去更新長度小的,所以對於每個元素,只要找到他能覆蓋的最大區間長度,然後只更新這個長度的答案即可,最後再整體用長度大的更新小的一次。求每個元素他能貢獻的最大的長度可以用單調棧。
程式碼:
#include<bits/stdc++.h> using namespace std; const int maxn = 5e5+5; int a[maxn], ans[maxn], n; int minl[maxn], minr[maxn]; int main(void) { while(cin >> n) { for(int i = 1; i <= n; i++) scanf("%d", &a[i]); memset(ans, 0, sizeof(ans)); stack<int> s; while(!s.empty()) s.pop(); for(int i = 1; i <= n; i++) { while(s.size() && a[s.top()] >= a[i]) s.pop(); minl[i] = s.size()==0 ? 1 : (s.top()+1); s.push(i); } while(!s.empty()) s.pop(); for(int i = n; i >= 1; i--) { while(s.size() && a[s.top()] >= a[i]) s.pop(); minr[i] = s.size()==0 ? n : (s.top()-1); s.push(i); } for(int i = 1; i <= n; i++) { int len = minr[i]-minl[i]+1; ans[len] = max(ans[len], a[i]); } for(int i = n-1; i >= 1; i--) ans[i] = max(ans[i], ans[i+1]); for(int i = 1; i <= n; i++) printf("%d%c", ans[i], i==n ? '\n' : ' '); } return 0; }