题意:给定一个长度为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;
}