bzoj 3123[Sdoi2013]森林 - 树上主席树 + 启发式合并

3123: [Sdoi2013]森林

Time Limit: 20 Sec  Memory Limit: 512 MB

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。之后的操作类似。 

 

 

 

一道树上主席树的练习题

查询x-y的链的大小时,我们的思路都是二分权值,但此时是以每一个树的节点为根,因此x-y这条链上的信息就等于

root[x] + root[y] - root[lca(x, y)] - root[fa(lca(x, y))]

每一个节点的线段树都对应的是点到根的路径信息

合并就是启发式合并的操作,暴力加点

 

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <algorithm>
  5 #include <cmath>
  6 #define LL long long
  7 #define lc seg[x].ch[0]
  8 #define rc seg[x].ch[1]
  9 
 10 using namespace std;
 11 
 12 
 13 const int MAXN = 8e4 + 10, MAXM = 8e4 + 10;
 14 int N, M, T;
 15 int SIZE = 0;
 16 LL ans;
 17 LL lastans = 0;
 18 int sum;
 19 int size[MAXN];
 20 int cnt = 0;
 21 int tot = 0;
 22 int root[MAXN];
 23 int deep[MAXN];
 24 int ra[MAXN];
 25 int val[MAXN];
 26 int head[MAXN];
 27 int testcase;
 28 int fa[30][MAXN];
 29 int father[MAXN];
 30 char opr[10];
 31 
 32 struct node {
 33     int val;
 34     int id;
 35 } n[MAXN];
 36 
 37 inline LL read()
 38 {
 39     LL x = 0, w = 1; char ch = 0;
 40     while(ch < '0' || ch > '9') {
 41         if(ch == '-') {
 42             w = -1;
 43         }
 44         ch = getchar();
 45     }
 46     while(ch >= '0' && ch <= '9') {
 47         x = x * 10 + ch - '0';
 48         ch = getchar();
 49     }
 50     return x * w;
 51 }
 52 
 53 struct segment {
 54     int ch[2];
 55     int num;
 56 } seg[MAXN * 200];
 57 
 58 int find(int x)
 59 {
 60     if(x != father[x]) {
 61         x = find(father[x]);
 62     }
 63     return father[x];
 64 }
 65 
 66 void pushup(int x)
 67 {
 68     seg[x].num = seg[lc].num + seg[rc].num;
 69 }
 70 
 71 struct edge {
 72     int v;
 73     int next;
 74 } g[MAXN * 10];
 75 
 76 void addedge(int u, int v)
 77 {
 78     g[++cnt].v = v;
 79     g[cnt].next = head[u];
 80     head[u] = cnt;
 81 }
 82 
 83 void init()
 84 {
 85     for(int i = 1; i < MAXN; i++) {
 86         father[i] = i;
 87     }
 88 }
 89 
 90 void multify()
 91 {
 92     for(int j = 1; j < 20; j++) {
 93         for(int i = 1; i <= N; i++) {
 94             fa[j][i] = fa[j - 1][fa[j - 1][i]];
 95         }
 96     }
 97 }
 98 
 99 void insert(int l, int r, int &x, int k)
100 {
101     seg[++tot] = seg[x];
102     x = tot;
103     if(l == r) {
104         seg[x].num++;
105         return;
106     }
107     int mid = (l + r) >> 1;
108     if(k > mid) {
109         insert(mid + 1, r, rc, k);
110     } else {
111         insert(l, mid, lc, k);
112     }
113     pushup(x);
114 }
115 
116 void build(int x, int top)
117 {
118     sum++;
119     father[x] = top;
120     deep[x] = deep[fa[0][x]] + 1;
121     root[x] = root[fa[0][x]];
122     insert(1, SIZE, root[x], ra[x]);
123     for(int j = head[x]; j; j = g[j].next) {
124         int to = g[j].v;
125         if(fa[0][to] == 0 && to != top) {
126             fa[0][to] = x;
127             build(to, top);
128         }
129     }
130 }
131 
132 void merge(int x, int f)
133 {
134     fa[0][x] = f;
135     deep[x] = deep[fa[0][x]] + 1;
136     for(int j = 1; j < 20; j++) {
137         fa[j][x] = fa[j - 1][fa[j - 1][x]];
138     }
139     root[x] = root[fa[0][x]];
140     insert(1, SIZE, root[x], ra[x]);
141     for(int j = head[x]; j; j = g[j].next) {
142         int to = g[j].v;
143         if(to != f) {
144             merge(to, x);
145         }
146     }
147 }
148 
149 void print(int l, int r, int x)
150 {
151     cout<<l<<" "<<r<<" "<<seg[x].num<<endl;
152     if(l == r) {
153         return;
154     }
155     int mid = (l + r) >> 1;
156     print(l, mid, lc);
157     print(mid + 1, r, rc);
158 }
159 
160 bool cmp(node a, node b)
161 {
162     return a.val < b.val;
163 }
164 
165 int get_lca(int x, int y)
166 {
167     if(deep[x] < deep[y]) {
168         swap(x, y);
169     }
170     for(int j = 20; j >= 0; j--) {
171         if(deep[fa[j][x]] >= deep[y]) {
172             x = fa[j][x];
173         }
174     }
175     if(x == y) {
176         return x;
177     }
178     for(int j = 20; j >= 0; j--) {
179         if(fa[j][x] != fa[j][y]) {
180             x = fa[j][x], y = fa[j][y];
181         }
182     }
183     return fa[0][x];
184 }
185 
186 void query(int l, int r, int x, int y, int lca, int fca, int k)
187 {
188     if(l == r) {
189         ans = val[l];
190         return;
191     }
192     int mid = (l + r) >> 1;
193     int NUM = seg[seg[x].ch[0]].num + seg[seg[y].ch[0]].num - seg[seg[lca].ch[0]].num - seg[seg[fca].ch[0]].num;
194     if(NUM >= k) {
195         query(l, mid, seg[x].ch[0], seg[y].ch[0], seg[lca].ch[0], seg[fca].ch[0], k);
196     } else {
197         query(mid + 1, r, seg[x].ch[1], seg[y].ch[1], seg[lca].ch[1], seg[fca].ch[1], k - NUM);
198     }
199 }
200 
201 int main()
202 {
203     init();
204     testcase = read();
205     N = read(), M = read(), T = read();
206     for(int i = 1; i <= N; i++) {
207         n[i].val = read();
208         n[i].id = i;
209     }
210     sort(n + 1, n + 1 + N, cmp);
211     ra[n[1].id] = SIZE = 1;
212     val[1] = n[1].val;
213     for(int i = 2; i <= N; i++) {
214         if(n[i].val == n[i - 1].val) {
215             ra[n[i].id] = SIZE;
216         } else {
217             ra[n[i].id] = ++SIZE;
218             val[SIZE] = n[i].val;
219         }
220     }
221     for(int i = 1; i <= M; i++) {
222         int u = read(), v = read();
223         addedge(u, v);
224         addedge(v, u);
225     }
226     for(int i = 1; i <= N; i++) {
227         sum = 0;
228         if(fa[0][i] == 0)
229             build(i, i);
230         size[i] = sum;
231     }
232     /*cout<<endl;
233     for(int i = 1; i <= N; i++) {
234         cout<<ra[i]<<" "<<val[i]<<endl; 
235     }*/
236 //    return 0;
237     multify();
238     /*cout<<endl;
239     for(int i = 1; i <= N; i++) {
240         cout<<fa[0][i]<<" "<<father[i]<<endl; 
241     }
242     for(int i = 1; i <= N; i++) {
243         cout<<i<<endl;
244         print(1, SIZE, root[i]);
245         cout<<endl<<endl;
246     }
247     return 0;*/
248     for(int i = 1; i <= T; i++) {
249         scanf("%s", opr);
250         if(opr[0] == 'Q') {
251             int x = read(), y = read(), k = read();
252             x = x ^ lastans, y = y ^ lastans, k = k ^ lastans; 
253         //    cout<<x<<" "<<y<<" "<<k<<endl;
254             int lca = get_lca(x, y); 
255             query(1, SIZE, root[x], root[y], root[lca], root[fa[0][lca]], k);
256             printf("%lld\n", ans);
257             lastans = ans;
258         } else {
259             int x = read(), y = read();
260             x = x ^ lastans, y = y ^ lastans;
261         //    cout<<x<<" "<<y<<endl; 
262             int u = find(x), v = find(y);
263         //    cout<<u<<" "<<v<<" "<<size[u]<<" "<<size[v]<<endl;
264             addedge(x, y);
265             addedge(y, x);
266             if(size[u] > size[v]) {
267                 size[u] += size[v];
268                 father[v] = u;
269                 merge(y, x);
270             } else {
271                 size[v] += size[u];
272                 father[u] = v;
273                 merge(x, y);
274             }
275                 //cout<<i<<endl;
276             //    print(1, SIZE, root[16]);
277             //    cout<<endl<<endl;
278             //    return 0;
279         }
280     }
281 }
282 
283 /*
284 1
285 20 12 20
286 412060525 42425138 67114752 160822495 201962681 926214957 380263349 733667141 869039239 641017702 154667400 461702107 438851950 176272938 209229857 985208975 762952138 936593832 409183276 999506034
287 2 17
288 4 1
289 15 3
290 3 10
291 9 10
292 7 16
293 19 15
294 13 2
295 6 2
296 3 14
297 7 18
298 8 15
299 Q 6 17 2
300 Q 762952152 762952154 762952139
301 L 380263329 380263352
302 L 380263357 380263333
303 Q 380263356 380263359 380263348
304 L 641017709 641017703
305 L 641017716 641017700
306 Q 641017716 641017704 641017698
307 Q 380263359 380263357 380263345
308 L 733667140 733667136
309 L 733667150 733667156
310 L 733667145 733667142
311 Q 733667149 733667145 733667140
312 Q 67114772 67114761 67114759
313 Q 733667145 733667159 733667142
314 Q 380263359 380263356 380263351
315 Q 869039233 869039232 869039237
316 Q 380263359 380263345 380263356
317 Q 733667136 733667140 733667143
318 Q 412060537 412060516 412060519
319 */
View Code

 

posted @ 2018-06-07 15:53  大财主  阅读(150)  评论(0编辑  收藏  举报