題目鏈接:https://www.luogu.com.cn/problem/P3224
這題的平衡樹寫法
實測不開o2的情況下權值線段樹快些,開了o2後最後一個數據平衡樹更快
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
typedef long long ll;
const int NN=100100;
const int inf=0x3f3f3f3f;
ll n,m,k,x,y,z,q,W,T,N,cnt,tmp,dst,cas,val,tot,num;
string s;char ch;
int fa[NN],id[NN];
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> rb_Tree;
rb_Tree rbt[NN];
int father(int x){
if(x==fa[x]) return x;
return fa[x]=father(fa[x]);
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>tmp;id[tmp]=i;fa[i]=i;
rbt[i].insert(tmp);
}
for(int i=1;i<=m;i++){
cin>>x>>y;
x=father(x);y=father(y);
if(x==y) continue;
if(rbt[x].size()>rbt[y].size()) swap(x,y);
//平衡樹的join功能合併的兩棵樹一棵的值域必須嚴格小於另一棵,不能用
//迭代器遍歷,啓發式合併
for(rb_Tree::point_iterator it=rbt[x].begin();it!=rbt[x].end();it++)
rbt[y].insert(*it);
rbt[x].clear();
fa[x]=y;
}
int q;cin>>q;
for(int i=1;i<=q;i++){
cin>>ch;
if(ch=='Q'){
cin>>x>>k;
int siz=rbt[father(x)].size();
if(k>siz) {
cout<<-1<<endl;
continue;
}
int t=*(rbt[father(x)].find_by_order(k-1));
cout<<id[t]<<endl;
}
else{
cin>>x>>y;
x=father(x);y=father(y);
if(x==y) continue;
if(rbt[x].size()>rbt[y].size()) swap(x,y);
for(rb_Tree::point_iterator it=rbt[x].begin();it!=rbt[x].end();it++)
rbt[y].insert(*it);
rbt[x].clear();
fa[x]=y;
}
}
}