并查集+treap维护的第k大数
#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;
struct Node{
int val, l, r, rnd, sze, hav;
}nd[200005];
int n, m, fa[200005], hmn[200005], opt, num, siz, uu, vv, rot;
void upd(int k){
nd[k].sze = nd[nd[k].l].sze + nd[nd[k].r].sze + nd[k].hav;
}
void lRotate(int &k){
int t=nd[k].r; nd[k].r = nd[t].l; nd[t].l = k;
nd[t].sze = nd[k].sze; upd(k); k = t;
}
void rRotate(int &k){
int t=nd[k].l; nd[k].l = nd[t].r; nd[t].r = k;
nd[t].sze = nd[k].sze; upd(k); k = t;
}
void ins(int &k, int x){
if(!k){
k = ++siz; nd[k].val = x;
nd[k].sze = nd[k].hav = 1; nd[k].rnd = rand();
return ;
}
nd[k].sze++;
if(nd[k].val==x) nd[k].hav++;
else if(nd[k].val<x){
ins(nd[k].r, x);
if(nd[nd[k].r].rnd<nd[k].rnd) lRotate(k);
}
else{
ins(nd[k].l, x);
if(nd[nd[k].l].rnd<nd[k].rnd) rRotate(k);
}
}
void del(int &k, int x){
if(!k) return ;
if(nd[k].val==x){
if(nd[k].hav>1){
nd[k].sze--; nd[k].hav--;
return ;
}
if(nd[k].l*nd[k].r==0) k = nd[k].l + nd[k].r;
else if(nd[nd[k].l].rnd<nd[nd[k].r].rnd)
rRotate(k), del(k, x);
else
lRotate(k), del(k, x);
}
else if(nd[k].val<x) nd[k].sze--, del(nd[k].r, x);
else nd[k].sze--, del(nd[k].l, x);
}
int myfind(int x){
return fa[x]==x?x:fa[x]=myfind(fa[x]);
}
int queryNum(int k, int x){
if(!k) return 0;
if(nd[nd[k].r].sze>=x) return queryNum(nd[k].r, x);
else if(nd[nd[k].r].sze+nd[k].hav<x) return queryNum(nd[k].l, x-nd[nd[k].r].sze-nd[k].hav);
else return nd[k].val;
}
int main(){
cin>>n>>m;
for(int i=1; i<=n; i++){
fa[i] = i;
hmn[i] = 1;
ins(rot, 1);
}
for(int i=1; i<=m; i++){
scanf("%d %d", &opt, &uu);
if(!opt) scanf("%d", &vv);
if(!opt){
uu = myfind(uu);
vv = myfind(vv);
if(uu!=vv){
int tmp=0;
tmp += hmn[uu];
tmp += hmn[vv];
del(rot, hmn[uu]);
del(rot, hmn[vv]);
ins(rot, tmp);
hmn[uu] += hmn[vv];
fa[vv] = uu;
}
}
else printf("%d
", queryNum(rot, uu));
}
return 0;
}