cychester

BZOJ 3123 [SDOI2013] 森林 - 启发式合并 主席树

Description

给你一片森林, 支持两个操作: 查询$x$到$y$的$K$大值,  连接两棵树中的两个点

Solution

对每个节点$x$动态开权值线段树, 表示从$x$到根节点路径上权值出现的次数。

查询时差分即可: $sum[x]+sum[y]-sum[lca]-sum[f[lca]]$

连边时需要启发式合并,将节点数小的接到节点数大的上去, 再遍历小的树, 并更新权值

 

我刚开始以为testcase是数据组数, TLE我好久,,

 

Code

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define rd read()
  5 using namespace std;
  6 
  7 const int N = 1e5;
  8 
  9 int lson[N * 100], rson[N * 100], sum[N * 100], root[N];
 10 int n, m, T, a[N], b[N], f[N][25], head[N], tot, dep[N];
 11 int father[N], num[N], cnt, nd_num;
 12 int lastans, Case; 
 13 
 14 struct edge {
 15     int nxt, to;
 16 }e[N << 2];
 17 
 18 int read() {
 19     int X = 0, p = 1; char c = getchar();
 20     for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
 21     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
 22     return X * p;
 23 }
 24 
 25 void add(int u, int v) {
 26     e[++tot].to = v;
 27     e[tot].nxt = head[u];
 28     head[u] = tot;
 29 }
 30 
 31 int find_anc(int x) {
 32     return father[x] == x ? x : father[x] = find_anc(father[x]);
 33 }
 34 
 35 int find_lca(int x, int y) {
 36     if(dep[x] < dep[y]) swap(x, y);
 37     for(int i = 20; ~i; --i) if(dep[f[x][i]] >= dep[y])
 38         x = f[x][i];
 39     if(x == y) return x;
 40     for(int i = 20; ~i; --i) if(f[x][i] != f[y][i])
 41         x = f[x][i], y = f[y][i];
 42     return f[x][0];
 43 }
 44 
 45 int fd(int x) {
 46     return lower_bound(b + 1, b + 1 + cnt, x) - b;
 47 }
 48 
 49 void ins(int &o, int now, int l, int r, int pos) {
 50     o = ++nd_num;
 51     sum[o] = sum[now] + 1;
 52     lson[o] = lson[now];
 53     rson[o] = rson[now];
 54     if(l == r) return;
 55     int mid = (l + r) >> 1;
 56     if(pos <= mid) ins(lson[o], lson[now], l, mid, pos);
 57     else ins(rson[o], rson[now], mid + 1, r, pos);
 58 }
 59 
 60 int query(int x, int y, int lca, int flca, int l, int r, int k) {
 61     if(l == r) return l;
 62     int mid = (l + r) >> 1, tmp;
 63     if((tmp = sum[lson[x]] + sum[lson[y]] - sum[lson[lca]] - sum[lson[flca]]) >= k) return query(lson[x], lson[y], lson[lca], lson[flca], l, mid, k);
 64     else return query(rson[x], rson[y], rson[lca], rson[flca], mid + 1, r, k - tmp);
 65 }
 66 
 67 void dfs(int u) {
 68     dep[u] = dep[f[u][0]] + 1;
 69     for(int i = 1; i <= 20; ++i)
 70         f[u][i] = f[f[u][i - 1]][i - 1];
 71     ins(root[u], root[f[u][0]], 1, cnt, fd(a[u]));
 72     for(int i = head[u]; i; i = e[i].nxt) {
 73         int nt = e[i].to;
 74         if(nt == f[u][0]) continue;
 75         f[nt][0] = u;
 76         dfs(nt);
 77     }
 78 }
 79 
 80 int work() {
 81     lastans = 0; tot = 0;
 82     nd_num = 0;
 83 /*    memset(root, 0, sizeof(root));
 84     memset(lson, 0, sizeof(lson));
 85     memset(rson, 0, sizeof(rson));
 86     memset(head, 0, sizeof(head));
 87     memset(dep, 0, sizeof(dep));*/
 88     n = rd; m = rd; T = rd;
 89     for(int i = 1; i <= n; ++i) b[i] = a[i] = rd;
 90     sort(b + 1, b + 1 + n);
 91     cnt = unique(b + 1, b + 1 + n) - b - 1;
 92     for(int i = 1; i <= n; ++i) father[i] = i, num[i] = 1;
 93     for(int i = 1; i <= m; ++i) {
 94         int u = rd, v = rd;
 95         int x = find_anc(u), y = find_anc(v);
 96         father[y] = x;
 97         num[x] += num[y];
 98         add(u, v); add(v, u);
 99     }
100     for(int i = 1; i <= n; ++i) if(!dep[i]) dfs(i);
101     for(int i = 1; i <= T; ++i) {
102         char c = getchar();
103         while(c != 'Q' && c != 'L') c = getchar();
104         int u = rd ^ lastans, v = rd ^ lastans;
105         if(c == 'Q') {
106             int lca = find_lca(u, v), flca = f[lca][0], k = rd ^ lastans;
107             lastans = query(root[u], root[v], root[lca], root[flca], 1, cnt, k);
108             if(lastans > cnt || lastans < 0) return printf("F**k,WA\n"), 0;
109             lastans = b[lastans];
110             printf("%d\n", lastans);
111         }
112         else {
113             int x = find_anc(u), y = find_anc(v);
114             if(num[x] < num[y]) {
115                 swap(x, y); swap(u, v);
116             }
117             father[y] = x;
118             num[x] += num[y];
119             f[v][0] = u;
120             add(v, u); add(u, v);
121             dfs(v);
122         }
123     }
124     return 0;
125 }
126 
127 int main()
128 {
129     Case = rd;
130     work();
131 }
View Code

 

posted on 2018-09-10 17:21  cychester  阅读(173)  评论(0编辑  收藏  举报

导航