Codeforces Round #305 (Div. 2) D题 (线段树+RMQ)

D. Mike and Feet
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

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.

Input

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.

Output

Print n integers in one line. For each x from 1 to n, print the maximum strength among all groups of size x.

Sample test(s)
input
10
1 2 3 4 5 4 3 2 1 6
output
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("
");
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/jie-dcai/p/4536967.html