永無鄉包含 n 座島,編號從 1 到 n,每座島都有本身的獨一無二的重要度,按照重要度可 以將這 n 座島排名,名次用 1 到 n 來表示。某些島之間由巨大的橋鏈接,經過橋能夠從一個島 到達另外一個島。若是從島 a 出發通過若干座(含 0 座)橋能夠到達島 b,則稱島 a 和島 b 是連 通的。如今有兩種操做:B x y 表示在島 x 與島 y 之間修建一座新橋。Q x k 表示詢問當前與島 x連通的全部島中第 k 重要的是哪座島,即全部與島 x 連通的島中重要度排名第 k 小的島是哪 座,請你輸出那個島的編號。
node
對於 20%的數據 n≤1000,q≤1000
對於 100%的數據 n≤100000,m≤n,q≤300000 ios
輸入文件第一行是用空格隔開的兩個正整數 n 和 m,分別 表示島的個數以及一開始存在的橋數。接下來的一行是用空格隔開的 n 個數,依次描述從島 1 到島 n 的重要度排名。隨後的 m 行每行是用空格隔開的兩個正整數 ai 和 bi,表示一開始就存 在一座鏈接島 ai 和島 bi 的橋。後面剩下的部分描述操做,該部分的第一行是一個正整數 q, 表示一共有 q 個操做,接下來的 q 行依次描述每一個操做,操做的格式如上所述,以大寫字母 Q 或B 開始,後面跟兩個不超過 n 的正整數,字母與數字以及兩個數字之間用空格隔開。spa
對於每一個 Q x k 操做都要依次輸出一行,其中包含一個整數,表 示所詢問島嶼的編號。若是該島嶼不存在,則輸出-1。 code
咦爲何以前線段樹合併專題的時候我沒寫這題……blog
大水題套路題,權值線段樹維護每一個聯通塊,並查集維護加邊,每次合併聯通塊時線段樹合併便可。ip
10分鐘寫完即AC爽爽string
1 #include<algorithm>
2 #include<iostream>
3 #include<cstring>
4 #include<cstdio>
5 #include<cmath>
6 #include<queue>
7 #define inf 2147483647
8 #define eps 1e-9
9 using namespace std; 10 typedef long long ll; 11 typedef double db; 12 struct node{ 13 int ls,rs,v; 14 }t[2000001]; 15 int n,m,q,u,v,cnt=0,fa[100001],rts[100001],num[100001],nmd[100001]; 16 char op[3]; 17 int ff(int u){ 18 return fa[u]==u?u:fa[u]=ff(fa[u]); 19 } 20 void updata(int &u,int l,int r,int x){ 21 if(!u)u=++cnt; 22 if(l==r){ 23 t[u].v=1; 24 return; 25 } 26 int mid=(l+r)/2; 27 if(x<=mid)updata(t[u].ls,l,mid,x); 28 else updata(t[u].rs,mid+1,r,x); 29 t[u].v=t[t[u].ls].v+t[t[u].rs].v; 30 } 31 int merge(int x,int y){ 32 if(!x||!y)return x|y; 33 t[x].ls=merge(t[x].ls,t[y].ls); 34 t[x].rs=merge(t[x].rs,t[y].rs); 35 t[x].v=t[t[x].ls].v+t[t[x].rs].v; 36 return x; 37 } 38 int query(int u,int l,int r,int k){ 39 if(l==r){ 40 return l; 41 } 42 int mid=(l+r)/2; 43 if(t[t[u].ls].v>=k)return query(t[u].ls,l,mid,k); 44 else return query(t[u].rs,mid+1,r,k-t[t[u].ls].v); 45 } 46 int main(){ 47 scanf("%d%d",&n,&m); 48 for(int i=1;i<=n;i++){ 49 scanf("%d",&num[i]); 50 fa[i]=nmd[num[i]]=i; 51 } 52 for(int i=1;i<=m;i++){ 53 scanf("%d%d",&u,&v); 54 int fu=ff(u),fv=ff(v); 55 if(fu!=fv){ 56 fa[fu]=fv; 57 } 58 } 59 for(int i=1;i<=n;i++){ 60 int fu=ff(i); 61 updata(rts[fu],1,n,num[i]); 62 } 63 scanf("%d",&q); 64 while(q--){ 65 scanf("%s%d%d",op,&u,&v); 66 if(op[0]=='Q'){ 67 int fu=ff(u); 68 if(t[rts[fu]].v<v){ 69 puts("-1"); 70 }else printf("%d\n",nmd[query(rts[fu],1,n,v)]); 71 }else{ 72 int fu=ff(u),fv=ff(v); 73 if(fu!=fv){ 74 fa[fu]=fv; 75 rts[fv]=merge(rts[fu],rts[fv]); 76 } 77 } 78 } 79 return 0; 80 }