解剖一棵树

树链剖分

别的不说,先%为敬%%%%%%%%%

写个LCA,跑的比HKjournalistTarjan还快,把倍增吊起来打......

反正就是那样,重儿子是为了保证时间复杂度。

DFS_1要求出d,fa,son,siz

DFS_2要求出top,id(剖出来的下标)

基本思路是靠着top最多会经过log次,不断跳top

重链剖出来是连续的,可以区间操作。

树剖求LCA:

 1 #include <cstdio>
 2 
 3 const int N = 500010;
 4 
 5 struct Edge {
 6     int v, nex;
 7 }edge[N << 1]; int t;
 8 int e[N], A[N], root, num;
 9 int top[N], son[N], fa[N], siz[N], id[N], d[N];
10 
11 inline void add(int x, int y) {
12     t++;
13     edge[t].v = y;
14     edge[t].nex = e[x];
15     e[x] = t;
16     return;
17 }
18 
19 void DFS_1(int x, int deep, int f) {
20     d[x] = deep;
21     siz[x] = 1;
22     fa[x] = f;
23     for(int i = e[x]; i; i = edge[i].nex) {
24         int y = edge[i].v;
25         if(y == f) {
26             continue;
27         }
28         DFS_1(y, deep + 1, x);
29         siz[x] += siz[y];
30         if(siz[y] > siz[son[x]]) {
31             son[x] = y;
32         }
33     }
34     return;
35 }
36 
37 void DFS_2(int x, int k) {
38     top[x] = k;
39     id[x] = ++num;
40     A[num] = x;
41     if(son[x]) {
42         DFS_2(son[x], k);
43     }
44     for(int i = e[x]; i; i = edge[i].nex) {
45         int y = edge[i].v;
46         if(y == son[x] || y == fa[x]) {
47             continue;
48         }
49         DFS_2(y, y);
50     }
51     return;
52 }
53 
54 inline int lca(int x, int y) {
55     while(top[x] != top[y]) {
56         if(d[top[x]] > d[top[y]]) {
57             x = fa[top[x]];
58         }
59         else {
60             y = fa[top[y]];
61         }
62     }
63     return d[x] > d[y] ? y : x;
64 }
65 
66 int main() {
67     int n, m;
68     scanf("%d%d%d", &n, &m, &root);
69     int x, y;
70     for(int i = 1; i < n; i++) {
71         scanf("%d%d", &x, &y);
72         add(x, y);
73         add(y, x);
74     }
75     DFS_1(root, 1, 0);
76     DFS_2(root, root);
77     while(m--) {
78         scanf("%d%d", &x, &y);
79         printf("%d\n", lca(x, y));
80     }
81     return 0;
82 }
AC代码

接下来是水题狂练,狂K水题,水门专题......


HAOI2015 树上操作

省选出树剖模板还行。

  1 #include <cstdio>
  2 typedef long long LL;
  3 const int N = 100010;
  4 
  5 struct Edge {
  6     int v, nex;
  7 }edge[N << 1]; int t;
  8 int e[N], A[N], root, num;
  9 int d[N], fa[N], top[N], son[N], id[N], siz[N];
 10 
 11 int n;
 12 LL sum[N << 2], tag[N << 2], val[N];
 13 
 14 inline void add(int x, int y) {
 15     t++;
 16     edge[t].v = y;
 17     edge[t].nex = e[x];
 18     e[x] = t;
 19     return;
 20 }
 21 
 22 void DFS_1(int x, int deep, int f) {
 23     fa[x] = f;
 24     siz[x] = 1;
 25     d[x] = deep;
 26     for(int i = e[x]; i; i = edge[i].nex) {
 27         int y = edge[i].v;
 28         if(y == f) {
 29             continue;
 30         }
 31         DFS_1(y, deep + 1, x);
 32         siz[x] += siz[y];
 33         if(siz[y] > siz[son[x]]) {
 34             son[x] = y;
 35         }
 36     }
 37     return;
 38 }
 39 
 40 void DFS_2(int x, int k) {
 41     top[x] = k;
 42     id[x] = ++num;
 43     A[num] = x;
 44     if(son[x]) {
 45         DFS_2(son[x], k);
 46     }
 47     for(int i = e[x]; i; i = edge[i].nex) {
 48         int y = edge[i].v;
 49         if(y == fa[x] || y == son[x]) {
 50             continue;
 51         }
 52         DFS_2(y, y);
 53     }
 54     return;
 55 }
 56 
 57 inline void pushup(int l, int r, int o) {
 58     if(l == r) {
 59         return;
 60     }
 61     sum[o] = sum[o << 1] + sum[o << 1 | 1];
 62     return;
 63 }
 64 
 65 inline void pushdown(int l, int r, int o) {
 66     if(l == r) {
 67         tag[o] = 0;
 68         return;
 69     }
 70     if(!tag[o]) {
 71         return;
 72     }
 73     int mid = (l + r) >> 1;
 74     int ls = o << 1;
 75     int rs = ls | 1;
 76     LL k = tag[o];
 77 
 78     tag[ls] += k;
 79     tag[rs] += k;
 80     sum[ls] += k * (mid - l + 1);
 81     sum[rs] += k * (r - mid);
 82 
 83     tag[o] = 0;
 84     return;
 85 }
 86 
 87 inline void build(int l, int r, int o) {
 88     if(l == r) {
 89         sum[o] = val[A[r]];
 90         return;
 91     }
 92     int mid = (l + r) >> 1;
 93     build(l, mid, o << 1);
 94     build(mid + 1, r, o << 1 | 1);
 95     pushup(l, r, o);
 96     return;
 97 }
 98 
 99 inline void add(int L, int R, LL v, int l, int r, int o) {
100     if(L <= l && r <= R) {
101         tag[o] += v;
102         sum[o] += v * (r - l + 1);
103         return;
104     }
105     pushdown(l, r, o);
106     int mid = (l + r) >> 1;
107     if(L <= mid) {
108         add(L, R, v, l, mid, o << 1);
109     }
110     if(mid < R) {
111         add(L, R, v, mid + 1, r, o << 1 | 1);
112     }
113     pushup(l, r, o);
114     return;
115 }
116 
117 inline LL ask(int L, int R, int l, int r, int o) {
118     if(L <= l && r <= R) {
119         return sum[o];
120     }
121     if(r < L || R < l) {
122         return 0;
123     }
124     pushdown(l, r, o);
125     int mid = (l + r) >> 1;
126     return ask(L, R, l, mid, o << 1) + ask(L, R, mid + 1, r, o << 1 | 1);
127 }
128 
129 inline LL ask(int x) {
130     LL ans = 0;
131     while(top[x] != root) {
132         ans += ask(id[top[x]], id[x], 1, n, 1);
133         x = fa[top[x]];
134     }
135     ans += ask(id[root], id[x], 1, n, 1);
136     return ans;
137 }
138 
139 int main() {
140     int m;
141     scanf("%d%d", &n, &m);
142     for(int i = 1; i <= n; i++) {
143         scanf("%lld", &val[i]);
144     }
145     root = 1;
146     int x, f;
147     LL y;
148     for(int i = 1; i < n; i++) {
149         scanf("%d%d", &x, &y);
150         add(x, y);
151         add(y, x);
152     }
153     DFS_1(root, 1, 0);
154     DFS_2(root, root);
155     build(1, n, 1);
156     while(m--) {
157         scanf("%d", &f);
158         if(f == 1) {
159             scanf("%d%lld", &x, &y);
160             add(id[x], id[x], y, 1, n, 1);
161         }
162         else if(f == 2) {
163             scanf("%d%lld", &x, &y);
164             add(id[x], id[x] + siz[x] - 1, y, 1, n, 1);
165         }
166         else {
167             scanf("%d", &x);
168             printf("%lld\n", ask(x));
169         }
170     }
171     return 0;
172 }
AC代码

洛谷 P3950 部落冲突

仔细思考发现这TM不就是树剖裸题吗?

如果删边就边权为1,加边则为0,联通条件是链权为0

  1 #include <cstdio>
  2 
  3 const int N = 300010;
  4 
  5 struct Edge {
  6     int v, nex;
  7 }edge[N << 1]; int t;
  8 int e[N], d[N], siz[N], son[N], fa[N], id[N], top[N];
  9 int num, A[N], B[N], sum[N << 2], n;
 10 
 11 inline void add(int x, int y) {
 12     t++;
 13     edge[t].v = y;
 14     edge[t].nex = e[x];
 15     e[x] = t;
 16     return;
 17 }
 18 
 19 void DFS_1(int x, int deep, int f) {
 20     siz[x] = 1;
 21     fa[x] = f;
 22     d[x] = deep;
 23     for(int i = e[x]; i; i = edge[i].nex) {
 24         int y = edge[i].v;
 25         if(y == f) {
 26             continue;
 27         }
 28         DFS_1(y, deep + 1, x);
 29         siz[x] += siz[y];
 30         if(siz[y] > siz[son[x]]) {
 31             son[x] = y;
 32         }
 33     }
 34     return;
 35 }
 36 
 37 void DFS_2(int x, int k) {
 38     top[x] = k;
 39     id[x] = ++num;
 40     A[num] = x;
 41     if(son[x]) {
 42         DFS_2(son[x], k);
 43     }
 44     for(int i = e[x]; i; i = edge[i].nex) {
 45         int y = edge[i].v;
 46         if(y == fa[x] || y == son[x]) {
 47             continue;
 48         }
 49         DFS_2(y, y);
 50     }
 51     return;
 52 }
 53 
 54 inline void pushup(int l, int r, int o) {
 55     if(l == r) {
 56         return;
 57     }
 58     sum[o] = sum[o << 1] + sum[o << 1 | 1];
 59     return;
 60 }
 61 
 62 void build(int l, int r, int o) {
 63     if(l == r) {
 64         sum[o] = 0;
 65         return;
 66     }
 67     int mid = (l + r) >> 1;
 68     build(l, mid, o << 1);
 69     build(mid + 1, r, o << 1 | 1);
 70     pushup(l, r, o);
 71     return;
 72 }
 73 
 74 int ask(int L, int R, int l, int r, int o) {
 75     if(L <= l && r <= R) {
 76         return sum[o];
 77     }
 78     if(r < L || R < l) {
 79         return 0;
 80     }
 81     int mid = (l + r) >> 1;
 82     return ask(L, R, l, mid, o << 1) + ask(L, R, mid + 1, r, o << 1 | 1);
 83 }
 84 
 85 void change(int p, int a, int l, int r, int o) {
 86     if(l == r) {
 87         sum[o] = a;
 88         return;
 89     }
 90     int mid = (l + r) >> 1;
 91     if(p <= mid) {
 92         change(p, a, l, mid, o << 1);
 93     }
 94     else {
 95         change(p, a, mid + 1, r, o << 1 | 1);
 96     }
 97     pushup(l, r, o);
 98     return;
 99 }
100 
101 inline int ask(int x) {
102     int ans = 0;
103     while(x) {
104         ans += ask(id[top[x]], id[x], 1, n, 1);
105         x = fa[top[x]];
106     }
107     return ans;
108 }
109 
110 inline int lca(int x, int y) {
111     while(top[x] != top[y]) {
112         if(d[top[x]] > d[top[y]]) {
113             x = fa[top[x]];
114         }
115         else {
116             y = fa[top[y]];
117         }
118     }
119     return d[x] > d[y] ? y : x;
120 }
121 
122 int main() {
123     int m, x, y;
124     char c[20];
125     scanf("%d%d", &n, &m);
126     for(int i = 1; i < n; i++) {
127         scanf("%d%d", &x, &y);
128         add(x, y);
129         add(y, x);
130     }
131     DFS_1(1, 1, 0);
132     DFS_2(1, 1);
133     build(1, n, 1);
134     num = 0;
135     for(int i = 1; i <= m; i++) {
136         scanf("%s", c);
137         scanf("%d", &x);
138         if(c[0] == 'Q') {
139             scanf("%d", &y);
140             int t = ask(x) + ask(y) - (ask(lca(x, y)) << 1);
141             if(t) {
142                 printf("No\n");
143             }
144             else {
145                 printf("Yes\n");
146             }
147         }
148         else if(c[0] == 'C') {
149             scanf("%d", &y);
150             A[++num] = x;
151             B[num] = y;
152             if(fa[y] == x) {
153                 x = y;
154             }
155             change(id[x], 1, 1, n, 1);
156         }
157         else {
158             y = A[x];
159             x = B[x];
160             if(fa[y] == x) {
161                 x = y;
162             }
163             change(id[x], 0, 1, n, 1);
164         }
165     }
166     return 0;
167 }
AC代码

 

posted @ 2018-07-23 20:49  garage  阅读(...)  评论(...编辑  收藏