BZOJ 3123: [Sdoi2013]森林

3123: [Sdoi2013]森林

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 2745  Solved: 808
[Submit][Status][Discuss]

Description

 

Input

第一行包含一个正整数testcase,表示当前测试数据的测试点编号。保证1≤testcase≤20。 
第二行包含三个整数N,M,T,分别表示节点数、初始边数、操作数。第三行包含N个非负整数表示 N个节点上的权值。 
 接下来 M行,每行包含两个整数x和 y,表示初始的时候,点x和点y 之间有一条无向边, 接下来 T行,每行描述一个操作,格式为“Q x y k”或者“L x y ”,其含义见题目描述部分。

Output

对于每一个第一类操作,输出一个非负整数表示答案。 
 
 

Sample Input

1
8 4 8
1 1 2 2 3 3 4 4
4 7
1 8
2 4
2 1
Q 8 7 3 Q 3 5 1
Q 10 0 0
L 5 4
L 3 2 L 0 7
Q 9 2 5 Q 6 1 6

Sample Output

2
2
1
4
2

HINT

 



对于第一个操作 Q 8 7 3,此时 lastans=0,所以真实操作为Q 8^0 7^0 3^0,也即Q 8 7 3。点8到点7的路径上一共有5个点,其权值为4 1 1 2 4。这些权值中,第三小的为 2,输出 2,lastans变为2。对于第二个操作 Q 3 5 1 ,此时lastans=2,所以真实操作为Q 3^2 5^2 1^2 ,也即Q 1 7 3。点1到点7的路径上一共有4个点,其权值为 1 1 2 4 。这些权值中,第三小的为2,输出2,lastans变为 2。之后的操作类似。 

 

 

Source

 
[Submit][Status][Discuss]

 

首先,考虑一下如果没有加边操作,可以怎么做呢?主席树吧,每个点上挂一个版本,由树上父亲的版本修改而来,包含该点到根路径上所有点的权值信息。查询的时候只需要取出x,y上的答案,去掉lca(x,y),lca(x,y).father的答案即可得到x到y路径上的答案了。

 

因为有加边操作,每次需要重新DFS处理主席树,按秩合并的思想,保留原本大小大的一棵树不变,重新DFS小的一棵即可。

 

复杂度$O(Nlog^{2}N)$

 

 1 #include <bits/stdc++.h>
 2 const int siz = 200005, tre = 20000005;
 3 int n, m, q, val[siz], map[siz], tot, hd[siz], to[siz], nt[siz], edge, root[siz], ls[tre], rs[tre], sm[tre], cnt, vis[siz], fa[siz][25], dep[siz], bl[siz], sz[siz], qa[siz], qb[siz], tail;
 4 inline int find(int u) { return bl[u] == u ? u : bl[u] = find(bl[u]); }
 5 inline void Union(int a, int b) { a = find(a), b = find(b); if (a ^ b)bl[a] = b, sz[b] += sz[a]; }
 6 void insert(int &t, int f, int l, int r, int p) {
 7     t = ++cnt; ls[t] = ls[f], rs[t] = rs[f], sm[t] = sm[f] + 1;
 8     if (l != r) { int mid = (l + r) >> 1; (p <= mid ? insert(ls[t], ls[f], l, mid, p) : insert(rs[t], rs[f], mid + 1, r, p)); }
 9 }
10 void dfs(int u, int f) { vis[u] = 1; 
11     if (u && f)Union(u, f); 
12     dep[u] = dep[f] + 1, fa[u][0] = f;
13     insert(root[u], root[f], 1, tot, val[u]);
14     for (int i = 1; i < 25; ++i)fa[u][i] = fa[fa[u][i - 1]][i - 1];
15     for (int i = hd[u]; i; i = nt[i])if (to[i] != f)dfs(to[i], u);
16 }
17 inline int lca(int a, int b) {
18     if (dep[a] < dep[b])a ^= b ^= a ^= b;
19     for (int i = 24; ~i; --i)if (dep[fa[a][i]] >= dep[b])a = fa[a][i];
20     for (int i = 24; ~i; --i)if (fa[a][i] ^ fa[b][i])a = fa[a][i], b = fa[b][i];
21     return a == b ? a : fa[a][0];
22 }
23 inline void add(int a, int b) { qa[tail] = root[a], qb[tail++] = b; }
24 int qry(int l, int r, int k) { if (l == r)return l; int s = 0, mid = (l + r) >> 1; 
25     for (int i = 0; i < tail; ++i)s += qb[i] * sm[ls[qa[i]]];
26     for (int i = 0; i < tail; ++i)qa[i] = s < k ? rs[qa[i]] : ls[qa[i]];
27     return s < k ? qry(mid + 1, r, k - s) : qry(l, mid, k);
28 }
29 inline void adde(int x, int y) {
30     nt[++edge] = hd[x], to[edge] = y, hd[x] = edge,
31     nt[++edge] = hd[y], to[edge] = x, hd[y] = edge;
32 }
33 signed main(void) {
34     scanf("%*d%d%d%d", &n, &m, &q);
35     for (int i = 1; i <= n; ++i)scanf("%d", val + i), map[++tot] = val[i], sz[i] = 1, bl[i] = i;
36     std::sort(map + 1, map + tot + 1); tot = std::unique(map + 1, map + tot + 1) - map;
37     for (int i = 1; i <= n; ++i)val[i] = std::lower_bound(map + 1, map + tot, val[i]) - map;
38     for (int i = 1, x, y; i <= m; ++i)scanf("%d%d", &x, &y), adde(x, y);
39     for (int i = 1; i <= n; ++i)if (!vis[i])dfs(i, 0);
40     for (int i = 1, ans = 0, x, y, k, t; i <= q; ++i) { char c = getchar(); while (c != 'Q' && c != 'L')c = getchar();
41         if (c == 'L') { scanf("%d%d", &x, &y), x ^= ans, y ^= ans, adde(x, y); if (sz[find(x)] > sz[find(y)])dfs(y, x); else dfs(x, y); }
42         else scanf("%d%d%d", &x, &y, &k), x ^= ans, y ^= ans, k ^= ans, tail = 0, 
43         add(x, 1), add(y, 1), add(t = lca(x, y), -1), add(fa[t][0], -1), printf("%d\n", ans = map[qry(1, tot, k)]);
44     }
45 }

 

发现我代码写长了就有毒…… 300+代码无限RE中

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 
  6 inline char nextC(void)
  7 {
  8     static const int siz = 1024;
  9     
 10     static char buf[siz];
 11     static char *hd = buf + siz;
 12     static char *tl = buf + siz;
 13     
 14     if (hd == tl)
 15         fread(hd = buf, 1, siz, stdin);
 16         
 17     return *hd++;
 18 }
 19 
 20 inline int nextI(void)
 21 {
 22     register int ret = 0;
 23     register int neg = false;
 24     register int bit = nextC();
 25     
 26     for (; bit < 48; bit = nextC())
 27         if (bit == '-')neg ^= true;
 28         
 29     for (; bit > 47; bit = nextC())
 30         ret = ret * 10 + bit - 48;
 31         
 32     return neg ? -ret : ret;
 33 }
 34 
 35 inline bool nextO(void)
 36 {
 37     register char c = nextC();
 38     
 39     while (c != 'Q' && c != 'L')
 40         c = nextC();
 41         
 42     return c == 'Q';
 43 }
 44 
 45 const int siz = 1000005;
 46 
 47 int n, m, q;
 48 
 49 int val[siz];
 50 int map[siz], tot;
 51 
 52 inline void initMap(void)
 53 {
 54     tot = 0;
 55     
 56     for (int i = 1; i <= n; ++i)
 57         map[++tot] = val[i];
 58         
 59 //    printf("tot = %d\n", tot);
 60 //    
 61 //    for (int i = 1; i < tot; ++i)
 62 //        printf("%d ", map[i]);
 63 //    puts("");
 64         
 65     using namespace std;
 66     
 67     sort(map + 1, map + tot + 1);
 68     
 69     tot = unique(map + 1, map + tot + 1) - map;
 70     
 71     for (int i = 1; i <= n; ++i)
 72         val[i] = lower_bound(map + 1, map + tot, val[i]) - map;
 73         
 74 //    printf("tot = %d\n", tot);
 75 //    
 76 //    for (int i = 1; i < tot; ++i)
 77 //        printf("%d ", map[i]);
 78 //    puts("");
 79 }
 80 
 81 int edge;
 82 int hd[siz];
 83 int nt[siz];
 84 int to[siz];
 85 
 86 inline void initEdge(void)
 87 {
 88     edge = 0;
 89     memset(hd, -1, sizeof(hd));
 90 //    static int sz = sizeof(int);
 91 //    memset(hd, -1, sz * (n + 5));
 92 }
 93     
 94 
 95 inline void addEdge(int x, int y)
 96 {
 97     nt[edge] = hd[x]; to[edge] = y; hd[x] = edge++;
 98     nt[edge] = hd[y]; to[edge] = x; hd[y] = edge++;
 99 }
100 
101 int cnt;
102 int root[siz];
103 int ls[siz * 20];
104 int rs[siz * 20];
105 int sm[siz * 20];
106 
107 inline void initTree(void)
108 {
109     cnt = 0;
110     memset(root, 0, sizeof(root));
111 //    static int sz = sizeof(int);
112 //    memset(root, 0, sz * (n + 5));
113 }
114 
115 void insert(int &t, int f, int l, int r, int p, int v)
116 {
117     t = ++cnt;
118     
119     ls[t] = ls[f];
120     rs[t] = rs[f];
121     sm[t] = sm[f] + v;
122     
123 //    printf("%d %d %d %d\n", t, l, r, sm[t]);
124     
125     if (l != r)
126     {
127         int mid = (l + r) >> 1;
128         
129         if (p <= mid)
130             insert(ls[t], ls[f], l, mid, p, v);
131         else
132             insert(rs[t], rs[f], mid + 1, r, p, v);
133     }
134 }
135 
136 int fa[siz][25], dep[siz];
137 
138 inline void initLCA(void)
139 {
140     memset(dep, 0, sizeof(dep));
141 //    static int sz = sizeof(int);
142 //    memset(dep, 0, sz * (n + 5));
143 }
144 
145 inline int lca(int a, int b)
146 {
147     if (dep[a] < dep[b])
148         a ^= b ^= a ^= b;
149         
150     for (int i = 24; i >= 0; --i)
151         if (dep[fa[a][i]] >= dep[b])
152             a = fa[a][i];
153     
154     if (a == b)return a;
155         
156     for (int i = 24; i >= 0; --i)
157         if (fa[a][i] != fa[b][i])
158             a = fa[a][i],
159             b = fa[b][i];
160             
161     return fa[a][0];
162 }
163 
164 int f[siz], g[siz];
165 
166 inline void initUnion(void)
167 {
168     for (int i = 0; i <= n; ++i)
169         f[i] = i, g[i] = 1;
170 }
171 
172 inline int find(int u)
173 {
174     static int stk[siz], top = 0;
175     
176     while (f[u] != u)
177         stk[++top] = u, u = f[u];
178         
179     while (top)
180         f[stk[top--]] = u;
181         
182     return u;
183 }
184 
185 inline void Union(int a, int b)
186 {
187     if (!a)return;
188     if (!b)return;
189     
190     a = find(a);
191     b = find(b);
192     
193     if (a != b)
194     {
195         g[b] += g[a];
196         f[a] = b;
197     }
198 }
199 
200 void dfs(int u, int fr)
201 {
202 //    printf("debug: dfs %d %d\n", u, fr);
203     
204     Union(u, fr);
205     
206     fa[u][0] = fr;
207     
208     dep[u] = dep[fr] + 1;
209     
210     for (int i = 1; i < 25; ++i)
211         fa[u][i] = fa[fa[u][i - 1]][i - 1];
212         
213     insert(root[u], root[fr], 1, tot, val[u], 1);
214         
215     for (int i = hd[u]; ~i; i = nt[i])
216         if (to[i] != fr)dfs(to[i], u);
217 }
218 
219 int queA[siz], queB[siz], tail;
220 
221 inline void initQue(void)
222 {
223     tail = 0;
224 }
225 
226 inline void addQue(int a, int b)
227 {
228     queA[tail] = root[a];
229     queB[tail++] = b;
230 }
231 
232 int query(int l, int r, int k)
233 {
234     if (l == r)return l;
235     
236     int s = 0, mid = (l + r) >> 1;
237     
238     for (int i = 0; i < tail; ++i)
239         s += sm[ls[queA[i]]] * queB[i];
240         
241     if (s >= k)
242     {
243         for (int i = 0; i < tail; ++i)
244             queA[i] = ls[queA[i]];
245             
246         return query(l, mid, k);
247     }
248     else
249     {
250         for (int i = 0; i < tail; ++i)
251             queA[i] = rs[queA[i]];
252             
253         return query(mid + 1, r, k - s);
254     }
255 }
256 
257 int ans;
258 
259 signed main(void)
260 {
261     for (int cas = nextI(); cas--; )
262     {
263         n = nextI();
264         m = nextI();
265         q = nextI();
266         
267         for (int i = 1; i <= n; ++i)
268             val[i] = nextI();
269         
270         initMap();
271         initEdge();
272         initTree();
273         initUnion();
274         
275         for (int i = 1; i <= m; ++i)
276         {
277             int x = nextI();
278             int y = nextI();
279             addEdge(x, y);
280         }
281         
282         for (int i = 1; i <= n; ++i)
283             if (g[find(i)] == 1)
284                 dfs(i, 0);
285         
286 //        puts("debug: prework finished");
287                 
288         for (int i = 1; i <= q; ++i)
289         {
290             if (nextO())    // Query
291             {
292                 int x = nextI() ^ ans;
293                 int y = nextI() ^ ans;
294                 int k = nextI() ^ ans;
295                 
296                 int t = lca(x, y);
297                 
298 //                printf("debug: lca %d %d = %d\n", x, y, t);
299                 
300                 initQue();
301                 
302                 addQue(x, +1);
303                 addQue(y, +1);
304                 addQue(t, -1);
305                 addQue(fa[t][0], -1);
306                 
307 //                for (int i = 0; i < tail; ++i)
308 //                    printf("que %d %d\n", queA[i], queB[i]);
309                 
310                 printf("%d\n", ans = map[query(1, tot, k)]);
311             }
312             else    // Link
313             {
314                 int x = nextI() ^ ans;
315                 int y = nextI() ^ ans;
316                 
317                 if (g[find(x)] > g[find(y)])
318                     dfs(y, x);
319                 else
320                     dfs(x, y);
321             }
322         }
323     }
324 }
325 /*
326 1
327 8 4 8
328 1 1 2 2 3 3 4 4
329 4 7
330 1 8
331 2 4
332 2 1
333 Q 8 7 3 
334 Q 3 5 1 
335 Q 10 0 0 
336 L 5 4 
337 L 3 2 
338 L 0 7 
339 Q 9 2 5 
340 Q 6 1 6
341 */
View Code

 

@Author: YouSiki

 

posted @ 2017-01-10 10:51  YouSiki  阅读(203)  评论(0编辑  收藏  举报