P3224 [HNOI2012]永无乡

大致题意

给一颗\(n\)个节点带点权图,现在有\(m\)次操作,操作分为两种:

  • 询问当前与\(u\)联通的第\(k\)大权值是哪个

  • 连接两个节点\(u,v\)

\(n,m≤10^5\)

分析

并查集+线段树合并

维护一个并查集,在合并两个节点\(u\)\(v\)的时候把它们的线段树也合并起来

复杂度\((n+m)logn\)

\(code\)

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100010;
int fa[MAXN];
inline int read(){
	int X=0; bool flag=1; char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
	while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
	if(flag) return X;
	return ~(X-1);
}
struct st{
	int lson,rson,val,pos;
}tree[MAXN*100];
int tot,root[MAXN];
int val[MAXN];
int n,m;
void pushup(int node){
	tree[node].val = tree[tree[node].lson].val+tree[tree[node].rson].val;
}
void insert(int &node,int l,int r,int pos,int val,int ind){
	if(!node) node = ++tot;
	if(l==r){
		tree[node].val+=val;
		tree[node].pos = ind;
		return;
	}
	int mid = (l+r)>>1;
	if(pos<=mid) insert(tree[node].lson,l,mid,pos,val,ind);
	else if(pos>mid) insert(tree[node].rson,mid+1,r,pos,val,ind);
	pushup(node);
}
int query(int node,int l,int r,int k){
	if(!node||tree[node].val<k){
	  return -1;	
	} 
	if(l==r){
		return tree[node].pos;
	}
	int mid =(l+r)>>1;
	if(k<=tree[tree[node].lson].val) return query(tree[node].lson,l,mid,k);
	else return query(tree[node].rson,mid+1,r,k-tree[tree[node].lson].val);
}
int merge(int node1,int node2,int l,int r){
	if(!node1) return node2;
	if(!node2) return node1;
	if(l==r){
		if(tree[node2].pos){
		tree[node1].pos = tree[node2].pos;
		tree[node1].val += tree[node2].val;
		}
		return node1;
	}
	int mid =(l+r)>>1;
	tree[node1].lson = merge(tree[node1].lson,tree[node2].lson,l,mid);
	tree[node1].rson = merge(tree[node1].rson,tree[node2].rson,mid+1,r);
	pushup(node1);
	return node1;
}
int find(int x){
	if(fa[x]==x) return x;
	return fa[x] = find(fa[x]);
} 
int main(){
	n = read(),m = read();
	for(int i=1;i<=n;i++){val[i] = read();
	fa[i] = i;
	insert(root[i],1,n,val[i],1,i);
	} 
	for(int i=1;i<=m;i++) {
	int u = read(),v = read();
	int x = find(u),y = find(v);
	fa[y] = x; 
	root[x] = merge(root[x],root[y],1,n);
	}
	int q = read();
	for(int i=1;i<=q;i++){
		char c;
		cin>>c;
		int u = read(),v = read();
		int x = find(u),y = find(v);
		if(c=='B'){
			if(x==y) continue;
			fa[y] = x;
			root[x] = merge(root[x],root[y],1,n);
		}
		else{
		    cout<<query(root[x],1,n,v)<<endl;
		}
	}
}
posted @ 2020-11-22 21:57  xcxc82  阅读(71)  评论(0编辑  收藏  举报