bzoj4034: [HAOI2015]树上操作（树链剖分）

bzoj4034

1、将某个节点的点权增加x。

2、将以某个节点x为根的子树中所有点的权值加上a。

3、询问某个节点x到根节点的所有点权和。

第二行n个整数，表示每个节点的权值。

接下来n - 1行每行两个整数，描述这棵树。

接下来m行描述了m个操作。

5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3

6
9
13

  1 #include<cstdio>
2 #include<vector>
3 #define ll long long
4 #define lc o << 1
5 #define rc o << 1 | 1
6 using namespace std;
7
8 const int maxn = 1e5 + 5;
9 int n, m, val[maxn];
10 ll sum[maxn * 4], bj[maxn * 4];
11 int dep[maxn], fa[maxn], top[maxn], size[maxn], seq[maxn], cnt, dfn[maxn], heavy[maxn];
12 vector <int> ve[maxn];
13
15     char c; while (c = getchar(), (c < '0' || c > '9') && c != '-'); int x = 0, y = 1;
16     if (c == '-') y = -1; else x = c - '0';
17     while (c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; return x * y;
18 }
19
20 void dfs1(int u, int pre) {
21     dep[u] = dep[pre] + 1;
22     fa[u] = pre; size[u] = 1;
23       for (int i = 0; i < ve[u].size(); ++ i) {
24           int v = ve[u][i];
25             if (v == pre) continue;
26           dfs1(v, u);
27           size[u] += size[v];
28             if (size[v] > size[heavy[u]]) heavy[u] = v;
29       }
30 }
31
32 void dfs2(int u, int cur) {
33     top[u] = cur; dfn[u] = ++ cnt;
34     seq[cnt] = u;
35       if (!heavy[u]) return;
36     dfs2(heavy[u], cur);
37       for (int i = 0; i < ve[u].size(); ++ i) {
38           int v = ve[u][i];
39             if (v == fa[u] || v == heavy[u]) continue;
40           dfs2(v, v);
41       }
42 }
43
44 void build(int o, int l, int r) {
45     if (l == r) {
46       sum[o] = val[seq[l]]; return;
47     }
48     int mid = l + r >> 1;
49     build(lc, l, mid); build(rc, mid + 1, r);
50     sum[o] = sum[lc] + sum[rc];
51 }
52
53 void pushdown(int o, int l, int r) {
54     int mid = l + r >> 1;
55     sum[lc] += bj[o] * (mid - l + 1);
56     sum[rc] += bj[o] * (r - mid);
57     bj[lc] += bj[o]; bj[rc] += bj[o]; bj[o] = 0;
58 }
59
60 void modify(int o, int l, int r, int ql, int qr, int c) {
61     if (ql <= l && qr >= r) {
62       sum[o] += 1ll * c * (r - l + 1); bj[o] += c;
63       return;
64     }
65     int mid = l + r >> 1;
66     if (bj[o]) pushdown(o, l, r);
67     if (ql <= mid) modify(lc, l, mid, ql, qr, c);
68     if (qr > mid) modify(rc, mid + 1, r, ql, qr, c);
69     sum[o] = sum[lc] + sum[rc];
70 }
71
72 ll query(int o, int l, int r, int ql, int qr) {
73     if (ql <= l && qr >= r) return sum[o];
74     int mid = l + r >> 1; ll ans = 0;
75     if (bj[o]) pushdown(o, l, r);
76     if (ql <= mid) ans += query(lc, l, mid, ql, qr);
77     if (qr > mid) ans += query(rc, mid + 1, r, ql, qr);
78     return ans;
79 }
80
81 ll chain_query(int x, int y) {
82     int fax = top[x], fay = top[y];
83     ll ans = 0;
84       while (fax != fay) {
85           if (dep[fax] < dep[fay]) {
86               swap(x, y);
87               swap(fax, fay);
88           }
89         ans += query(1, 1, n, dfn[fax], dfn[x]);
90         x = fa[fax];
91         fax = top[x];
92       }
93       if (dep[x] > dep[y]) swap(x, y);
94     ans += query(1, 1, n, dfn[x], dfn[y]);
95     return ans;
96 }
97
98 int main() {
100       for (int i = 1; i <= n; ++ i) val[i] = read();
101       for (int i = 1; i < n; ++ i) {
103           ve[x].push_back(y);
104           ve[y].push_back(x);
105       }
106     dfs1(1, 0);
107     dfs2(1, 1);
108     build(1, 1, n);
109       while (m --) {
111             if (opt == 1) { //单点加a
113                   modify(1, 1, n, dfn[x], dfn[x], a);
114             }
115           else if (opt == 2) {
125 }