大意:你有30000個隊列,第i個隊列中只有iide
有T個操做,1,把某個隊列頭接到另外一個隊列尾。spa
2,問兩個元素之間的距離。code
本題主要有三種解法。blog
①帶權並查集。隊列
具體來講就是,並查集維護當前集合的大小,這個點距離表明元(隊首)的邊數。io
而後把合併和路徑壓縮魔改一下。詢問的時候就直接取距離之差。event
1 #include <cstdio> 2 3 const int N = 30010; 4 5 int fa[N], sum[N], siz[N]; 6 char str[5]; 7 8 inline int find(int x, int &s) { 9 if(fa[x] == x) { 10 s = 0; 11 return x; 12 } 13 int t = find(fa[x], s); 14 s += sum[x]; 15 sum[x] = s; 16 return fa[x] = t; 17 } 18 19 inline void merge(int x, int y) { 20 int a, b; 21 x = find(x, a); 22 y = find(y, b); 23 fa[x] = y; 24 sum[x] = siz[y]; 25 siz[y] += siz[x]; 26 return; 27 } 28 29 inline int ask(int x, int y) { 30 int a, b; 31 x = find(x, a); 32 y = find(y, b); 33 if(x != y) { 34 return -1; 35 } 36 return (a > b ? a - b : b - a) - 1; 37 } 38 39 int main() { 40 int n; 41 scanf("%d", &n); 42 for(int i = 1; i <= 30000; i++) { 43 fa[i] = i; 44 siz[i] = 1; 45 } 46 for(int i = 1, x, y; i <= n; i++) { 47 scanf("%s%d%d", str, &x, &y); 48 if(str[0] == 'M') { 49 merge(x, y); 50 } 51 else { 52 printf("%d\n", ask(x, y)); 53 } 54 } 55 56 return 0; 57 }
②平衡樹class
這個太暴力了......開30000顆平衡樹便可。cli
③離線(kruskal重構樹)重構
重構的時候把順序搞一下,而後提出來DFS序,直接回答詢問。