大致题意
给一颗(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;
}
}
}