[洛谷P3833][SHOI2012]魔法树
题目大意:给一棵树,路径加,子树求和
题解:树剖
卡点:无
C++ Code:
#include <cstdio> #include <iostream> #define maxn 100010 int head[maxn], cnt; struct Edge { int to, nxt; } e[maxn << 1]; inline void add(int a, int b) { e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt; } int n, m; namespace SgT { long long V[maxn << 2], tg[maxn << 2]; int L, R, num; inline void pushdown(int rt, int len) { long long &__tg = tg[rt]; V[rt << 1] += __tg * (len + 1 >> 1); V[rt << 1 | 1] += __tg * (len >> 1); tg[rt << 1] += __tg; tg[rt << 1 | 1] += __tg; __tg = 0; } void __add(int rt, int l, int r) { if (L <= l && R >= r) { V[rt] += static_cast<long long> (r - l + 1) * num; tg[rt] += num; return ; } int mid = l + r >> 1; if (tg[rt]) pushdown(rt, r - l + 1); if (L <= mid) __add(rt << 1, l, mid); if (R > mid) __add(rt << 1 | 1, mid + 1, r); V[rt] = V[rt << 1] + V[rt << 1 | 1]; } void add(int __L, int __R, int __num) { L = __L, R = __R, num = __num; __add(1, 1, n); } long long __ask(int rt, int l, int r) { if (L <= l && R >= r) return V[rt]; int mid = l + r >> 1; long long ans = 0; if (tg[rt]) pushdown(rt, r - l + 1); if (L <= mid) ans = __ask(rt << 1, l, mid); if (R > mid) ans += __ask(rt << 1 | 1, mid + 1, r); return ans; } long long ask(int __L, int __R) { L = __L, R = __R; return __ask(1, 1, n); } } using SgT::add; using SgT::ask; int fa[maxn], dep[maxn], sz[maxn]; int dfn[maxn], idx, top[maxn], son[maxn]; void dfs1(int u) { sz[u] = 1; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (v != fa[u]) { fa[v] = u; dep[v] = dep[u] + 1; dfs1(v); sz[u] += sz[v]; if (!son[u] || sz[v] > sz[son[u]]) son[u] = v; } } } void dfs2(int u) { dfn[u] = ++idx; int v = son[u]; if (v) top[v] = top[u], dfs2(v); for (int i = head[u]; i; i = e[i].nxt) { v = e[i].to; if (v != fa[u] && v != son[u]) { top[v] = v; dfs2(v); } } } void modify(int x, int y, int z) { while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) std::swap(x, y); add(dfn[top[x]], dfn[x], z); x = fa[top[x]]; } if (dep[x] > dep[y]) std::swap(x, y); add(dfn[x], dfn[y], z); } long long query(int x) { return ask(dfn[x], dfn[x] + sz[x] - 1); } int main() { std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0); std::cin >> n; for (int i = 1, a, b; i < n; i++) { std::cin >> a >> b; a++, b++; add(a, b); add(b, a); } dfs1(1); top[1] = 1; dfs2(1); std::cin >> m; while (m --> 0) { char op; int x, y, z; std::cin >> op >> x; x++; if (op == 'A') { std::cin >> y >> z; y++; modify(x, y, z); } else std::cout << query(x) << '\n'; } return 0; }