永無鄉包含 n 座島,編號從 1 到 n,每座島都有自己的獨一無二的重要度,按照重要度可 以將這 n 座島排名,名次用 1 到 n 來表示。某些島之間由巨大的橋連接,通過橋可以從一個島 到達另一個島。如果從島 a 出發經過若干座(含 0 座)橋可以到達島 b,則稱島 a 和島 b 是連 通的。現在有兩種操作:B x y 表示在島 x 與島 y 之間修建一座新橋。Q x k 表示詢問當前與島 x連通的所有島中第 k 重要的是哪座島,即所有與島 x 連通的島中重要度排名第 k 小的島是哪 座,請你輸出那個島的編號。
輸入文件第一行是用空格隔開的兩個正整數 n 和 m,分別 表示島的個數以及一開始存在的橋數。接下來的一行是用空格隔開的 n 個數,依次描述從島 1 到島 n 的重要度排名。隨后的 m 行每行是用空格隔開的兩個正整數 ai 和 bi,表示一開始就存 在一座連接島 ai 和島 bi 的橋。后面剩下的部分描述操作,該部分的第一行是一個正整數 q, 表示一共有 q 個操作,接下來的 q 行依次描述每個操作,操作的格式如上所述,以大寫字母 Q 或B 開始,后面跟兩個不超過 n 的正整數,字母與數字以及兩個數字之間用空格隔開。 對于 20%的數據 n≤1000,q≤1000 對于 100%的數據 n≤100000,m≤n,q≤300000
對于每個 Q x k 操作都要依次輸出一行,其中包含一個整數,表 示所詢問島嶼的編號。如果該島嶼不存在,則輸出-1。
#include <cstdio>#include <algorithm>#include <iostream>using namespace std;const int maxx = 100000 + 100;int n,m,x,y,root,t;int father[maxx];char flag[2];struct Node{ int lc,rc; int v,fix; int size;}T[maxx];inline int read(){ int x=0,f=1;char c=getchar(); while(c>'9'||c<'0') {if(c == '-') f=-1; c=getchar();} while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();} return x*f;}void update(int i){ T[i].size = T[T[i].lc].size + T[T[i].rc].size + 1;}void lturn(int &i){ int t = T[i].rc; T[i].rc = T[t].lc; T[t].lc = i; T[t].size = T[i].size; update(i); i = t;}void rturn(int &i){ int t = T[i].lc; T[i].lc = T[t].rc; T[t].rc = i; T[t].size = T[i].size; update(i); i = t;}void insert(int &i,int x){ if(i == 0){ i = x; T[i].size = 1; T[i].lc = T[i].rc = 0; T[i].fix = rand(); return; } T[i].size++; if(T[x].v < T[i].v){ insert(T[i].lc,x); if(T[T[i].lc].fix < T[i].fix) rturn(i); } if(T[x].v > T[i].v){ insert(T[i].rc,x); if(T[T[i].rc].fix < T[i].fix) lturn(i); }}int Query_num(int i,int x){ int rank = T[T[i].lc].size; if(rank+1 == x) return i; else if(rank >= x) return Query_num(T[i].lc,x); else return Query_num(T[i].rc,x-rank-1);}int find(int x){ if(father[x]!=x) father[x] = find(father[x]); return father[x]; }void merge(int x,int y){ if(y == 0) return; merge(x,T[y].lc); merge(x,T[y].rc); insert(x,y);}void unionn(int x,int y){ int r1=find(x),r2=find(y); if(T[r1].size > T[r2].size) x^=y^=x^=y; father[r1]=r2; merge(r2,r1);} int main(){ n = read();m = read(); for(int i=1;i<=n;i++) T[i].v = read(),T[i].size = 1,father[i] = i; for(int i=1;i<=m;i++) x = read(),y = read(),unionn(x,y); t = read(); while( t-- ){ scanf("%s",flag); x = read();y = read(); if(flag[0] == 'B') unionn(x,y); else{ int fx = find(x); if(T[fx].size < y) PRintf("-1/n"); else printf("%d/n",Query_num(fx,y)); } } return 0;}
新聞熱點
疑難解答