Codeforces Round #305 (Div. 2) D题 (线段树+RMQ)
Mike is the president of country What-The-Fatherland. There are n bears living in this country besides Mike. All of them are standing in a line and they are numbered from 1 to n from left to right. i-th bear is exactly ai feet high.
A group of bears is a non-empty contiguous segment of the line. The size of a group is the number of bears in that group. The strengthof a group is the minimum height of the bear in that group.
Mike is a curious to know for each x such that 1 ≤ x ≤ n the maximum strength among all groups of size x.
The first line of input contains integer n (1 ≤ n ≤ 2 × 105), the number of bears.
The second line contains n integers separated by space, a1, a2, ..., an (1 ≤ ai ≤ 109), heights of bears.
Print n integers in one line. For each x from 1 to n, print the maximum strength among all groups of size x.
10
1 2 3 4 5 4 3 2 1 6
6 4 4 3 3 2 2 1 1 1
先用ST算法处理出一段区间内最小值。二分查询出对于第i个数,以它为最小向左或向右可达的最值,得到区间长度为r-l+1。那么,对于group长度为1,2,3,....r-l+1最小值为第i个数的值。则区间更新这些组大小,取最大值。此处可以使用线段树维护。
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; const int N=200050; const int inf=1e9+107; int feet[N]; int st[N][20]; int seg[N<<2]; int ans[N]; void pushdown(int rt){ seg[rt<<1]=max(seg[rt<<1],seg[rt]); seg[rt<<1|1]=max(seg[rt<<1|1],seg[rt]); seg[rt]=-1; } void ST(int num){ for(int i=1;i<=num;i++) st[i][0]=feet[i]; for(int j=1;j<20;j++) for(int i=1;i<=num;i++){ if(i+(1<<j)-1 <= num){ st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]); } } } void update(int rt,int l,int r,int L,int R,int val){ if(l<=L&&R<=r){ if(val>seg[rt]) seg[rt]=val; return; } int m=(L+R)>>1; pushdown(rt); if(r<=m){ update(rt<<1,l,r,L,m,val); } else if(l>=m+1){ update(rt<<1|1,l,r,m+1,R,val); } else{ update(rt<<1,l,r,L,m,val); update(rt<<1|1,l,r,m+1,R,val); } } void dfs(int rt,int L,int R){ if(L==R){ ans[L]=seg[rt]; return ; } pushdown(rt); int m=(L+R)>>1; dfs(rt<<1,L,m); dfs(rt<<1|1,m+1,R); } int query(int l,int r){ int k=(int)((log(r-l+1))/log(2.0)); int maxl=min(st[l][k],st[r-(1<<k)+1][k]); return maxl; } int main(){ int n; while(scanf("%d",&n)!=EOF){ for(int i=1;i<=(n<<2)+10;i++){ seg[i]=-1; } for(int i=1;i<=n;i++){ scanf("%d",&feet[i]); } ST(n); for(int i=1;i<=n;i++){ //left int l=1,r=i; int L=i,R=i; while(l<=r){ int m=(l+r)>>1; int index=query(m,i); if(index>=feet[i]){ r=m-1; L=m; } else { l=m+1; } } //right l=i,r=n; while(l<=r){ int m=(l+r)>>1; int index=query(i,m); if(index>=feet[i]){ l=m+1; R=m; } else { r=m-1; } } update(1,1,R-L+1,1,n,feet[i]); } dfs(1,1,n); printf("%d",ans[1]); for(int i=2;i<=n;i++) printf(" %d",ans[i]); printf("\n"); } return 0; }