COGS 2485. [HZOI 2016]从零开始的序列

2485. [HZOI 2016]从零开始的序列

★★   输入文件:sky_seq.in   输出文件:sky_seq.out   简单对比
时间限制:1 s   内存限制:256 MB

【题目描述】

这个名字只是吸引你们这些死宅过来的。跟题目没关系。

现在Sky_miner给你一个序列,定义f(x)为(所有长度为x的区间中的最小值)的最大值.

要求输出f(1) .. f(n)

1 <= n <= 2*10^5

【输入格式】

第一行一个正整数n,含义如题

第二行共n个整数,为给定的序列,每一个整数 -10000 <= x <= 10000

【输出格式】

一行,共n个正整数,分别为f(1) f(2) .. f(n)

【样例输入】

5
3 4 1 3 9

【样例输出】

9 3 1 1 1

【来源】

HZOI 2016

分析:

大概有两种做法...

一种是比较直接的并查集做法...

就是我们把元素从大到小排序,依次加入序列中,然后并查集维护联通块的大小,更新答案,最后因为$f[i]>=f[i+1]$再$O(N)$更新一遍就好了...

一种是单调栈做法...

维护$l[i]r[i]$代表以$a[i]$为最小值所能扩展到最远的子序列,然后更新答案...

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
using namespace std;

const int maxn=200000+5;

int n,a[maxn],f[maxn],fa[maxn],siz[maxn],pos[maxn],vis[maxn];

inline int read(void){
	char ch=getchar();int f=1,x=0;
	while(!(ch>='0'&&ch<='9')){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return f*x;
}

inline int find(int x){
	return fa[x]==x?x:fa[x]=find(fa[x]);
}

inline bool cmp(int x,int y){
	return a[x]>a[y];
}

signed main(void){
	freopen("sky_seq.in","r",stdin);
	freopen("sky_seq.out","w",stdout);
	n=read();memset(f,-1,sizeof(f));
	for(int i=1;i<=n;i++)
		a[i]=read(),fa[i]=i,siz[i]=1,pos[i]=i;
	sort(pos+1,pos+n+1,cmp);
	for(int i=1;i<=n;i++){
		vis[pos[i]]=1;
		if(pos[i]>1&&vis[pos[i]-1]){
			int fx=find(pos[i]-1);
			siz[pos[i]]+=siz[fx],fa[fx]=pos[i];
		}
		if(pos[i]<n&&vis[pos[i]+1]){
			int fx=find(pos[i]+1);
			siz[pos[i]]+=siz[fx],fa[fx]=pos[i];
		}
		if(f[siz[pos[i]]]==-1)
			f[siz[pos[i]]]=a[pos[i]];
	}
	for(int i=n-1;i>=1;i--)
		f[i]=max(f[i],f[i+1]);
	for(int i=1;i<=n;i++)
		printf("%d ",f[i]);puts("");
	fclose(stdin);fclose(stdout);
	return 0;
}

  


By NeighThorn

posted @ 2017-03-02 20:26  NeighThorn  阅读(257)  评论(0编辑  收藏  举报