

基本思路:
类似题目:
#include<cstdio>
#include<iostream>
using namespace std;
const int MAXN=1e7,INF=2e9;
struct Node{
int ls,rs;
int cnt;//被加次数
int pos;//岛屿编号
}tr[MAXN];
int nodeCnt=0;//权值线段树
int root[MAXN];
void insert(int &now,int l,int r,int x,int pos){
if(!now)now=++nodeCnt;
if(l==r){
tr[now].cnt++;
tr[now].pos=pos;
return;
}
int mid=(l+r)>>1;
if(x<=mid)insert(tr[now].ls,l,mid,x,pos);
else insert(tr[now].rs,mid+1,r,x,pos);
tr[now].cnt=tr[tr[now].ls].cnt+tr[tr[now].rs].cnt;
}
int merge(int p,int q,int l,int r){
if(!p)return q;
if(!q)return p;
if(l==r){
tr[p].cnt+=tr[q].cnt;
tr[p].pos=tr[q].pos;
return p;
}
int mid=(l+r)>>1;
tr[p].ls=merge(tr[p].ls,tr[q].ls,l,mid);
tr[p].rs=merge(tr[p].rs,tr[q].rs,mid+1,r);
tr[p].cnt=tr[tr[p].ls].cnt+tr[tr[p].rs].cnt;
return p;
}
int query(int now,int l,int r,int k){
if(l==r)return tr[now].pos;
if(tr[now].cnt<k)return -1;//不存在
int mid=(l+r)>>1;
int lsum=tr[tr[now].ls].cnt;
if(k<=lsum)return query(tr[now].ls,l,mid,k);
else return query(tr[now].rs,mid+1,r,k-lsum);
}
int fa[MAXN];
int get(int x){
while(x!=fa[x])x=fa[x]=fa[fa[x]];
return x;
}
int b_merge(int a,int b){//集合合并
fa[get(a)]=get(b);
return get(b);
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=n;i++){
int rank;//重要度
scanf("%d",&rank);
insert(root[i],-INF,INF,rank,i);
}
for(int i=1;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
a=get(a),b=get(b);
int rt=merge(root[a],root[b],-INF,INF);
b_merge(a,b);
root[a]=root[b]=rt;
}
int q;
scanf("%d",&q);//q个操作
for(int i=1;i<=q;i++){
char opt;
cin>>opt;
if(opt==‘B‘){
int x,y;
scanf("%d%d",&x,&y);//修一条新桥
x=get(x),y=get(y);
int rt=merge(root[x],root[y],-INF,INF);
b_merge(x,y);
root[x]=root[y]=rt;
}else if(opt==‘Q‘){
int x,k;
scanf("%d%d",&x,&k);
cout<<query(root[get(x)],-INF,INF,k)<<endl;
}
}
return 0;
}
原文:https://www.cnblogs.com/zbsy-wwx/p/11747721.html