题目大意:
在$n$个带权点上维护两个操作:
1)在点$u,v$间连一条边;
2)询问点$u$所在联通块中权值第$k$小的点的编号,若该联通块中的点的数目小于$k$,则输出$-1$;
上周的模拟赛在一道线段树合并的题目上gg了,来学习一个。
对每一个联通块,我们维护一棵权值线段树。查询时,若左子树大小大于等于$k$进入左子树,否则进入右子树;
因为每棵线段树同构,所以对于任意两棵线段树可以进行合并操作:
1 int merge(int x,int y){ 2 if(!x)return y; 3 if(!y)return x; 4 t[x].lson=merge(t[x].lson,t[y].lson); 5 t[x].rson=merge(t[x].rson,t[y].rson); 6 t[x].s=t[t[x].lson].s+t[t[x].rson].s; 7 return x; 8 }
利用并查集判断两个点是否连通,若不联通,则合并两个联通块的线段树即可;
代码:
1 #include<cstring> 2 #include<cmath> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cctype> 6 #define foru(i,x,y) for(int i=x;i<=y;i++) 7 using namespace std; 8 const int N=1e5+100; 9 10 struct node{int s,lson,rson;}t[N*20]; 11 int n,m,a[N],f[N],fx,fy,cnt,rt[N],idx[N]; 12 13 int gf(int k){return k==f[k]?k:f[k]=gf(f[k]);} 14 15 int read(){ 16 static int f,x;static char ch; 17 x=f=0;ch=getchar(); 18 while(!isdigit(ch)){f=(ch=='-');ch=getchar();} 19 while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();} 20 return f?-x:x; 21 } 22 23 #define ls t[k].lson 24 #define rs t[k].rson 25 #define mid ((L+R)>>1) 26 27 void upd(int &k,int L,int R,int p){ 28 if(p<L||p>R)return; 29 if(!k)k=++cnt; 30 if(L==R){t[k].s=1;return;} 31 upd(ls,L,mid,p);upd(rs,mid+1,R,p); 32 t[k].s=t[ls].s+t[rs].s; 33 } 34 35 int query(int k,int L,int R,int p){ 36 if(L==R)return L; 37 if(t[ls].s<p)return query(rs,mid+1,R,p-t[ls].s); 38 return query(ls,L,mid,p); 39 } 40 41 int merge(int x,int y){ 42 if(!x)return y; 43 if(!y)return x; 44 t[x].lson=merge(t[x].lson,t[y].lson); 45 t[x].rson=merge(t[x].rson,t[y].rson); 46 t[x].s=t[t[x].lson].s+t[t[x].rson].s; 47 return x; 48 } 49 50 int main(){ 51 //freopen("1.in","r",stdin); 52 memset(t,0,sizeof(t)); 53 n=read();m=read(); 54 foru(i,1,n)a[i]=read(),f[i]=i; 55 foru(i,1,m){ 56 fx=gf(read());fy=gf(read()); 57 f[fx]=fy; 58 } 59 foru(i,1,n){ 60 upd(rt[gf(i)],1,n,a[i]); 61 idx[a[i]]=i; 62 } 63 int q=read(),x,y; 64 char ch[10]; 65 while(q--){ 66 scanf("%s%d%d",ch,&x,&y); 67 fx=gf(x);fy=gf(y); 68 if(ch[0]=='Q') 69 printf("%d ",t[rt[fx]].s>=y?idx[query(rt[fx],1,n,y)]:-1); 70 else if(fx!=fy){ 71 f[fx]=fy; 72 rt[fy]=merge(rt[fx],rt[fy]); 73 } 74 } 75 return 0; 76 }