51nod 1437 迈克步——单调栈
有n只熊。他们站成一排队伍,从左到右依次1到n编号。第i只熊的高度是ai。
一组熊指的队伍中连续的一个子段。组的大小就是熊的数目。而组的力量就是这一组熊中最小的高度。
迈克想知道对于所有的组大小为x(1 ≤ x ≤ n)的,最大力量是多少。
Input
单组测试数据。 第一行有一个整数n (1 ≤ n ≤ 2×10^5),表示熊的数目。 第二行包含n个整数以空格分开,a1, a2, ..., an (1 ≤ ai ≤ 10^9),表示熊的高度。
Output
在一行中输出n个整数,对于x从1到n,输出组大小为x的最大力量。
Input示例
10 1 2 3 4 5 4 3 2 1 6
Output示例
6 4 4 3 3 2 2 1 1 1
求出以每个元素为最小值的区间的左边界和右边界,保存下来,r[i] - l[i] +1 就是a[i]可作为最小值的区间的最大长度,然后这个长度的区间肯定包含这个长度-1的区间,于是依次取最大值。
#include<stdio.h> #include<cstring> #include<iostream> #include<algorithm> #define MAXSIZE 200005 using namespace std; int a[MAXSIZE],l[MAXSIZE],r[MAXSIZE],s[MAXSIZE],ans[MAXSIZE]; int main() { freopen("in.txt","r",stdin); memset(ans,0,sizeof(ans)); memset(s,0,sizeof(s)); int n,top; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; top = 0; for(int i=1;i<=n;i++) { if(top==0) { s[++top] = i; l[i] = i; } else { while(top>=1 && a[s[top]]>=a[i]) { top--; } if(top==0) l[i] = 1; else l[i] = s[top]+1; s[++top] = i; } } top = 0; for(int i=n;i>=1;i--) { if(top==0) { s[++top] = i; r[i] = i; } else { while(top>=1 && a[s[top]]>=a[i]) { top--; } if(top==0) r[i] = n; else r[i] = s[top]-1; s[++top] = i; } } for(int i=1;i<=n;i++) { ans[r[i]-l[i]+1] = max(ans[r[i]-l[i]+1],a[i]); } for(int i=n-1;i>=1;i--) { ans[i] = max(ans[i+1],ans[i]); } for(int i=1;i<=n;i++) { if(i!=1) cout<<" "; cout<<ans[i]; } return 0; }