BZOJ 2733: [HNOI2012]永无乡

线段树合并

#include<cstdio>
using namespace std;
int cnt,F[100005],ls[2000005],rs[2000005],ID[2000005],sz[2000005],root[100005];
char s[15];
int find(int x){
	if (F[x]!=x) F[x]=find(F[x]);
	return F[x];
}
void insert(int &t,int l,int r,int x,int y){
	if (!t) t=++cnt;
	sz[t]++;
	if (l==r){
		ID[t]=y;
		return;
	}
	int mid=(l+r)>>1;
	if (x<=mid) insert(ls[t],l,mid,x,y);
	else insert(rs[t],mid+1,r,x,y);
}
int query(int t,int l,int r,int K){
	if (l==r) return ID[t];
	int mid=(l+r)>>1;
	if (K<=sz[ls[t]]) return query(ls[t],l,mid,K);
	else return query(rs[t],mid+1,r,K-sz[ls[t]]);
}
int merge(int x,int y){
	if (!x || !y) return x^y;
	sz[x]+=sz[y];
	ls[x]=merge(ls[x],ls[y]);
	rs[x]=merge(rs[x],rs[y]);
	return x;
}
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	for (int i=1; i<=n; i++){
		int x;
		scanf("%d",&x);
		insert(root[i],1,n,x,i);
	}
	for (int i=1; i<=n; i++) F[i]=i;
	for (int i=1; i<=m; i++){
		int x,y;
		scanf("%d%d",&x,&y);
		int fx=find(x),fy=find(y);
		if (fx!=fy) {
			F[fy]=fx;
			root[fx]=merge(root[fx],root[fy]);
		}
	}
	int q;
	scanf("%d",&q);
	while (q--){
		scanf("%s",s);
		if (s[0]=='Q'){
			int x,k;
			scanf("%d%d",&x,&k);
			int fx=find(x);
			if (sz[root[fx]]<k) printf("-1\n");
			else printf("%d\n",query(root[fx],1,n,k));
		}
		else{
			int x,y;
			scanf("%d%d",&x,&y);
			int fx=find(x),fy=find(y);
			if (fx!=fy){
				F[fy]=fx;
				root[fx]=merge(root[fx],root[fy]);
			}
		}
	}
	return 0;
}

  

posted @ 2018-10-23 19:24  ~Silent  阅读(124)  评论(0编辑  收藏  举报
Live2D