其他分享
首页 > 其他分享> > P3224 [HNOI2012]永无乡(线段树合并)

P3224 [HNOI2012]永无乡(线段树合并)

作者:互联网

支持加边和询问连通块第k大点权。

线段树合并即可。

//线段树合并
//每次合并两个连通块的权值线段树
//询问第k大 
#include<bits/stdc++.h>
using namespace std; 
const int maxn=1e5+10;
const int M=maxn*100;
int c[M],lson[M],rson[M],T[maxn],tot;
void pushup (int newRoot) {
	c[newRoot]=c[lson[newRoot]]+c[rson[newRoot]];
}
int up (int i,int l,int r,int p,int v) {
	int newRoot=i;
	if (!newRoot) newRoot=++tot;
	if (l==r) {
		c[newRoot]+=v;
		return newRoot;
	}
	int mid=(l+r)>>1;
	if (p<=mid) lson[newRoot]=up(lson[newRoot],l,mid,p,v);
	if (p>mid) rson[newRoot]=up(rson[newRoot],mid+1,r,p,v);
	pushup(newRoot);
	return newRoot;
}
int merge (int x,int y,int l,int r) {
	if (!x) return y;
	if (!y) return x;
	if (l==r) {
		c[x]+=c[y];
		return x;
	}
	int mid=(l+r)>>1;
	lson[x]=merge(lson[x],lson[y],l,mid);
	rson[x]=merge(rson[x],rson[y],mid+1,r);
	pushup(x);
	return x; 
}
int kth (int u,int l,int r,int k) {
	//在一颗权值树上找第k大
	if (l==r) return l;
	int mid=(l+r)>>1;
	if (c[lson[u]]<k) {
		return kth(rson[u],mid+1,r,k-c[lson[u]]);
	} 
	else {
		return kth(lson[u],l,mid,k);
	}
}
int father[maxn],n,m,sz[maxn];
int findfather (int x) {
	int a=x;
	while (x!=father[x]) x=father[x];
	while (a!=father[a]) {
		int z=a;
		a=father[a];
		father[z]=x;
	} 
	return x;
}
int p[maxn];
int b[maxn];
int main () {
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) father[i]=i,sz[i]=1;
	for (int i=1;i<=n;i++) scanf("%d",p+i),b[p[i]]=i;
	for (int i=1;i<=n;i++) T[i]=up(T[i],1,n,p[i],1);
	while (m--) {
		int x,y;
		scanf("%d%d",&x,&y);
		x=findfather(x);
		y=findfather(y);
		if (x==y) continue;
		father[x]=y;
		sz[y]+=sz[x];
		T[y]=merge(T[y],T[x],1,n);
	} 
	int q;
	scanf("%d",&q);
	while (q--) {
		string op;
		cin>>op;
		if (op=="Q") {
			int x,y;
			scanf("%d%d",&x,&y);
			x=findfather(x);
			if (y>sz[x]) printf("-1\n");
			else printf("%d\n",b[kth(T[x],1,n,y)]);
		}
		else {
			int x,y;
			scanf("%d%d",&x,&y);
			x=findfather(x);
			y=findfather(y);
			if (x==y) continue;
			father[x]=y;
			sz[y]+=sz[x];
			T[y]=merge(T[y],T[x],1,n);
		}
	}
}

标签:return,int,newRoot,线段,mid,HNOI2012,lson,P3224,rson
来源: https://www.cnblogs.com/zhanglichen/p/15110090.html