Luogu P3178 樹上操作(樹鏈剖分+線段樹)
阿新 • • 發佈:2018-11-01
題意
見原題
題解
重鏈剖分模板題
#include <cstdio> #include <algorithm> using std::swap; typedef long long ll; const int N = 1e5 + 10; int n, m, c[N], opt, x, y; int dep[N], siz[N], fa[N], son[N]; int top[N], dfn[N], w[N], time; int cnt, from[N], to[N << 1], nxt[N << 1]; ll val[N << 2], add[N << 2]; inline void addEdge(int u, int v){ to[++cnt] = v, nxt[cnt] = from[u], from[u] = cnt; } void dfs1(int u) { dep[u] = dep[fa[u]] + 1, siz[u] = 1; for (int i = from[u]; i; i = nxt[i]) { int v = to[i]; if(v == fa[u]) continue; fa[v] = u, dfs1(v), siz[u] += siz[v]; if(siz[v] > siz[son[u]]) son[u] = v; } } void dfs2(int u, int t) { top[u] = t, dfn[u] = ++time, w[time] = c[u]; if(!son[u]) return ; dfs2(son[u], t); for(int i = from[u]; i; i = nxt[i]) { int v = to[i]; if(v != fa[u] && v != son[u]) dfs2(v, v); } } inline void pushup(int o, int lc, int rc) { val[o] = val[lc] + val[rc]; } inline void pushdown(int o, int lc, int rc, int len) { if(add[o]) { add[lc] += add[o], add[rc] += add[o]; val[lc] += add[o] * (len - (len >> 1)); val[rc] += add[o] * (len >> 1); add[o] = 0; } } void build(int o = 1, int l = 1, int r = n) { if(l == r) { val[o] = w[l]; return ; } int mid = (l + r) >> 1, lc = o << 1, rc = lc | 1; build(lc, l, mid), build(rc, mid + 1, r), pushup(o, lc, rc); } void upt(int ul, int ur, ll k, int o = 1, int l = 1, int r = n) { if (l >= ul && r <= ur) { add[o] += k, val[o] += k * (r - l + 1); return ; } int mid = (l + r) >> 1, lc = o << 1, rc = lc | 1; pushdown(o, lc, rc, r - l + 1); if(ul <= mid) upt(ul, ur, k, lc, l, mid); if(ur > mid) upt(ul, ur, k, rc, mid + 1, r); pushup(o, lc, rc); } ll que(int ql, int qr, int o = 1, int l = 1, int r = n) { if (l >= ql && r <= qr) return val[o]; int mid = (l + r) >> 1, lc = o << 1, rc = lc | 1; ll ret = 0; pushdown(o, lc, rc, r - l + 1); if(ql <= mid) ret = que(ql, qr, lc, l, mid); if(qr > mid) ret += que(ql, qr, rc, mid + 1, r); return ret; } ll sum(int x) { int fx = top[x]; ll ret = 0; while (fx != 1) ret += que(dfn[fx], dfn[x]), x = fa[fx], fx = top[x]; return ret + que(1, dfn[x]); } int main () { scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) scanf("%d", c + i); for (int i = 1, u, v; i < n; ++i) { scanf("%d%d", &u, &v); addEdge(u, v), addEdge(v, u); } dfs1(1), dfs2(1, 1), build(); while(m--) { scanf("%d%d", &opt, &x); if (opt == 3) printf("%lld\n", sum(x)); else { scanf("%d", &y); if (opt == 1) upt(dfn[x], dfn[x], y); else upt(dfn[x], dfn[x] + siz[x] - 1, y); } } return 0; }