cogs 1341 永无乡
【题目描述】
永无乡包含 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。
【样例输入】
5 1 4 3 2 5 1 1 2 7 Q 3 2 Q 2 1 B 2 3 B 1 5 Q 2 1 Q 2 4 Q 2 3【样例输出】
-1 2 5 1 2
启发式合并么。。。
用并查集维护岛屿之间的连通性,并打上size标记来维护岛屿集合的大小。
用log数据结构维护每个岛屿集合的所有重要度排名。
合并的时候把小的集合暴力插入到大的集合里。
这样的话每次合并后大小至少乘以二。
最多乘log次,所以最后复杂度是nlog^2n(大概吧。。。)。
平衡树看起来都很难写啊。。。于是并没有写平衡树。。。
01trie还是很好的。。。
注意到n不超过10W。。。
也就是说树的最大深度就是17咯。。。
平衡树的最大深度也是1吧。。。
所以跑进了rank10???
至于01trie怎么合并。。。看置顶的那篇文章吧(神奇的log合并)。。。
STL的list是个坑。。。splice、size操作就是O(n)的。。。
所以手写了一个链表。。。(也就是说key值的合并是O(1)的了。。。当然没什么用。。。毕竟还有O(nlogn)的插入操作。。。)
不过这么说的话vector似乎就行了???
注意垃圾清理啊。。。不然内存要开O(nlog^2n)了(大概)。。。会MLE的(亲测,如果前面的假设没有错的话。。。)。。。
拍照留念?
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <list> 7 8 using namespace std; 9 10 const int N = 100010; 11 12 int n, m, q, x, y, id[N]; 13 char op[10]; 14 15 int GC[N], gcp; 16 17 int keys[N], hd[N], nxt[N], lst[N]; 18 19 int root[N], ch[N * 20][2], sum[N * 20]; 20 21 int New() { 22 static int cnt = 0; 23 if(gcp) { 24 int rt =GC[gcp --]; 25 if(rt[ch][0]) { 26 GC[++ gcp] = rt[ch][0]; 27 } 28 if(rt[ch][1]) { 29 GC[++ gcp] = rt[ch][1]; 30 } 31 rt[ch][0] = rt[ch][1] = 0; 32 rt[sum] = 0; 33 return rt; 34 } else { 35 return ++ cnt; 36 } 37 } 38 39 #define walk for(int i = 16, t ; (t = (val >> i) & 1), ~i ; i --) 40 41 void ins(int rt, int val) { 42 walk { 43 if(rt[ch][t] == 0) rt[ch][t] = New(); 44 (rt = rt[ch][t])[sum] ++; 45 } 46 } 47 48 int kth(int rt, int val) { 49 int ret = 0; 50 walk { 51 if(val > rt[ch][0][sum]) { 52 val -= rt[ch][0][sum]; 53 ret |= 1 << i; 54 rt = rt[ch][1]; 55 } else { 56 rt = rt[ch][0]; 57 } 58 } 59 return ret; 60 } 61 62 int acc[N], size[N]; 63 64 void init(int n) { 65 for(int i = 1 ; i <= n ; i ++) { 66 i[acc] = i; 67 i[size] = 1; 68 } 69 } 70 71 int find(int x) { 72 return x == x[acc] ? x : x[acc] = find(x[acc]); 73 } 74 75 void uni(int x, int y) { 76 x = find(x); 77 y = find(y); 78 if(x != y) { 79 y[size] += x[size]; 80 x[acc] = y; 81 } 82 } 83 84 void merge(int x, int y) { 85 x = find(x); 86 y = find(y); 87 if(x != y) { 88 if(x[size] > y[size]) { 89 swap(x, y); 90 } 91 for(int i = x[hd] ; i ; i = nxt[i]) { 92 ins(y, keys[i]); 93 if(nxt[i] == 0) { 94 y[lst][nxt] = x; 95 y[lst] = x[lst]; 96 } 97 } 98 GC[++ gcp] = x; 99 uni(x, y); 100 } 101 } 102 103 int ask(int rt, int k) { 104 rt = find(rt); 105 if(rt[size] < k) { 106 return -1; 107 } else { 108 int res = kth(rt, k); 109 return res[id]; 110 } 111 } 112 113 int main() { 114 freopen("bzoj_2733.in", "r", stdin); 115 freopen("bzoj_2733.out", "w", stdout); 116 scanf("%d%d", &n, &m); 117 init(n); 118 for(int i = 1 ; i <= n ; i ++) { 119 i[root] = New(); 120 } 121 for(int i = 1 ; i <= n ; i ++) { 122 scanf("%d", &x); 123 x[id] = i; 124 ins(i[root], x); 125 i[keys] = x; 126 i[hd] = i; 127 i[lst] = i; 128 } 129 for(int i = 1 ; i <= m ; i ++) { 130 scanf("%d%d", &x, &y); 131 merge(x, y); 132 } 133 scanf("%d", &q); 134 for(int i = 1 ; i <= q ; i ++) { 135 scanf("%s%d%d", op, &x, &y); 136 if(op[0] == 'B') { 137 merge(x, y); 138 } else { 139 printf("%d\n", ask(x, y)); 140 } 141 } 142 return 0; 143 }
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <vector> 7 8 #define walk for(int i = 16, t ; (t = (val >> i) & 1), ~i ; i --) 9 10 using namespace std; 11 12 const int N = 100010; 13 14 int n, m, q, x, y, id[N]; 15 16 char op[10]; 17 18 int GC[N], gcp; 19 20 vector<int> keys[N]; 21 22 int root[N], ch[N * 20][2], sum[N * 20]; 23 24 int acc[N], size[N]; 25 26 int New() { 27 static int cnt = 0; 28 if(gcp) { 29 int rt =GC[gcp --]; 30 if(rt[ch][0]) { 31 GC[++ gcp] = rt[ch][0]; 32 } 33 if(rt[ch][1]) { 34 GC[++ gcp] = rt[ch][1]; 35 } 36 rt[ch][0] = rt[ch][1] = 0; 37 rt[sum] = 0; 38 return rt; 39 } else { 40 return ++ cnt; 41 } 42 } 43 44 void ins(int rt, int val) { 45 walk { 46 if(rt[ch][t] == 0) rt[ch][t] = New(); 47 (rt = rt[ch][t])[sum] ++; 48 } 49 } 50 51 int kth(int rt, int val) { 52 int ret = 0; 53 walk { 54 if(val > rt[ch][0][sum]) { 55 val -= rt[ch][0][sum]; 56 ret |= 1 << i; 57 rt = rt[ch][1]; 58 } else { 59 rt = rt[ch][0]; 60 } 61 } 62 return ret; 63 } 64 65 void init(int n) { 66 for(int i = 1 ; i <= n ; i ++) { 67 i[acc] = i; 68 i[size] = 1; 69 } 70 } 71 72 int find(int x) { 73 return x == x[acc] ? x : x[acc] = find(x[acc]); 74 } 75 76 void uni(int x, int y) { 77 x = find(x); 78 y = find(y); 79 if(x != y) { 80 y[size] += x[size]; 81 x[acc] = y; 82 } 83 } 84 85 void merge(int x, int y) { 86 x = find(x); 87 y = find(y); 88 if(x != y) { 89 if(x[size] > y[size]) 90 swap(x, y); 91 for(int i = 0 ; i < x[keys].size() ; i ++) { 92 ins(y, x[keys][i]); 93 y[keys].push_back(x[keys][i]); 94 } 95 GC[++ gcp] = x; 96 uni(x, y); 97 } 98 } 99 100 int ask(int rt, int k) { 101 rt = find(rt); 102 if(rt[size] < k) { 103 return -1; 104 } else { 105 int res = kth(rt, k); 106 return res[id]; 107 } 108 } 109 110 int main() { 111 freopen("bzoj_2733.in", "r", stdin); 112 freopen("bzoj_2733.out", "w", stdout); 113 114 scanf("%d%d", &n, &m); 115 init(n); 116 for(int i = 1 ; i <= n ; i ++) { 117 i[root] = New(); 118 } 119 120 for(int i = 1 ; i <= n ; i ++) { 121 scanf("%d", &x); 122 x[id] = i; 123 ins(i[root], x); 124 i[keys].push_back(x); 125 } 126 127 for(int i = 1 ; i <= m ; i ++) { 128 scanf("%d%d", &x, &y); 129 merge(x, y); 130 } 131 132 scanf("%d", &q); 133 134 for(int i = 1 ; i <= q ; i ++) { 135 scanf("%s%d%d", op, &x, &y); 136 if(op[0] == 'B') { 137 merge(x, y); 138 } else { 139 printf("%d\n", ask(x, y)); 140 } 141 } 142 return 0; 143 }