直接平衡树启发式合并就好了。。。貌似是个很高端的东西。。
貌似可以证明splay的启发式合并是均摊$O(nlogn)$的。。。而其他平衡树都不行,所以其他的复杂度都是$O(nlog^2n)的$的
所以就用平板电视里的splay好啦!2333
1 /************************************************************** 2 Problem: 2733 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:2148 ms 7 Memory:9756 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <ext/pb_ds/assoc_container.hpp> 12 #include <ext/pb_ds/tree_policy.hpp> 13 14 using namespace std; 15 using namespace __gnu_pbds; 16 typedef tree<int, int, less<int>, splay_tree_tag, tree_order_statistics_node_update> Tree; 17 typedef Tree :: iterator iter; 18 const int N = 1e5 + 5; 19 20 int read(); 21 int get_op(); 22 23 int n, m; 24 int a[N]; 25 int fa[N], sz[N]; 26 Tree T[N]; 27 28 int find(int x) { 29 return x == fa[x] ? x : fa[x] = find(fa[x]); 30 } 31 32 void _union(int x, int y) { 33 iter it; 34 x = find(x), y = find(y); 35 if (x == y) return; 36 if (sz[x] < sz[y]) swap(x, y); 37 for (it = T[y].begin(); it != T[y].end(); ++it) 38 T[x][it -> first] = it -> second; 39 fa[y] = x, sz[x] += sz[y], T[y].clear(); 40 } 41 42 int query() { 43 int x = find(read()), k = read(); 44 if (k > T[x].size()) return -1; 45 return T[find(x)].find_by_order(k - 1) -> second; 46 } 47 48 int main() { 49 int i, Q, oper; 50 n = read(), m = read(); 51 for (i = 1; i <= n; ++i) { 52 a[i] = read(), fa[i] = i; 53 T[i][a[i]] = i; 54 } 55 for (i = 1; i <= m; ++i) _union(read(), read()); 56 for (Q = read(); Q; --Q) { 57 oper = get_op(); 58 if (oper == 0) _union(read(), read()); 59 else printf("%d\n", query()); 60 } 61 return 0; 62 } 63 64 inline int read() { 65 static int x; 66 static char ch; 67 x = 0, ch = getchar(); 68 while (ch < '0' || '9' < ch) 69 ch = getchar(); 70 while ('0' <= ch && ch <= '9') { 71 x = x * 10 + ch - '0'; 72 ch = getchar(); 73 } 74 return x; 75 } 76 77 inline int get_op() { 78 static char ch; 79 ch = getchar(); 80 while (ch != 'Q' && ch != 'B') ch = getchar(); 81 return ch == 'Q'; 82 }
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen