[Luogu] 魔法树
Posted xayata
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Luogu] 魔法树相关的知识,希望对你有一定的参考价值。
https://www.luogu.org/problemnew/show/P3833
树链剖分 + 线段树
为啥会RE?? 不解
#include <iostream> #include <cstdio> using namespace std; const int N = 1e5 + 10; #define LL long long int n, T, now = 1, tim; int top[N], tree[N], lst[N], rst[N], bef[N], size[N], fa[N], deep[N], son[N]; LL W[N << 2], F[N << 2], S[N << 2]; struct Node {int v, nxt;} G[N << 1]; int head[N]; LL Answer; #define gc getchar() inline int read() { int x = 0; char c = gc; while(c < ‘0‘ || c > ‘9‘) c = gc; while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = gc; return x; } inline void Add(int u, int v) {G[now].v = v; G[now].nxt = head[u]; head[u] = now ++;} struct Node_1 { #define lson jd << 1 #define rson jd << 1 | 1 void Build_tree(int l, int r, int jd) { S[jd] = r - l + 1; if(l == r) return ; int mid = (l + r) >> 1; Build_tree(l, mid, lson); Build_tree(mid + 1, r, rson); } void Down(int jd) { int f = F[jd]; F[lson] += f; F[rson] += f; W[lson] += S[lson] * f; W[rson] += S[rson] * f; F[jd] = 0; } void Sec_G(int l, int r, int jd, int x, int y, int yj) { if(x <= l && r <= y) { F[jd] += yj; W[jd] += S[jd] * yj; return ; } if(F[jd]) Down(jd); int mid = (l + r) >> 1; if(x <= mid) Sec_G(l, mid, lson, x, y, yj); if(y > mid ) Sec_G(mid + 1, r, rson, x, y, yj); W[jd] = W[lson] + W[rson]; } void Sec_A(int l, int r, int jd, int x, int y) { if(x <= l && r <= y) { Answer += W[jd]; return ; } if(F[jd]) Down(jd); int mid = (l + r) >> 1; if(x <= mid) Sec_A(l, mid, lson, x, y); if(y > mid ) Sec_A(mid + 1, r, rson, x, y); } }Seg_tree; void Dfs_1(int u, int f_, int dep) { fa[u] = f_; deep[u] = dep; size[u] = 1; for(int i = head[u]; ~ i; i = G[i].nxt) { int v = G[i].v; if(v != f_) { Dfs_1(v, u, dep + 1); size[u] += size[v]; if(size[son[u]] < size[v]) son[u] = v; } } } void Dfs_2(int u, int tp) { top[u] = tp; tree[u] = ++ tim; lst[u] = tim; if(!son[u]) {rst[u] = tim; return ;} Dfs_2(son[u], tp); for(int i = head[u]; ~ i; i = G[i].nxt) { int v = G[i].v; if(v != fa[u] && v != son[u]) Dfs_2(v, v); } rst[u] = tim; } inline void Sec_G_imp(int x, int y, int w) { int tp1 = top[x], tp2 = top[y]; while(tp1 != tp2) { if(deep[tp1] < deep[tp2]) swap(tp1, tp2), swap(x, y); Seg_tree.Sec_G(1, n, 1, tree[tp1], tree[x], w); x = fa[tp1]; tp1 = fa[x]; } if(deep[x] < deep[y]) swap(x, y); Seg_tree.Sec_G(1, n, 1, tree[y], tree[x], w); return ; } int main() { n = read(); for(int i = 0; i < n; i ++) son[i] = -1, head[i] = -1; for(int i = 1; i < n; i ++) {int u = read(), v = read(); Add(u, v);} Seg_tree.Build_tree(1, n, 1); Dfs_1(0, 0, 1); Dfs_2(0, 0); T = read(); while(T --) { string opt; cin >> opt; if(opt[0] == ‘A‘) { int x = read(), y = read(), w = read(); Sec_G_imp(x, y, w); } else { Answer = 0; int x = read(); Seg_tree.Sec_A(1, n, 1, lst[x], rst[x]); cout << Answer << "\n"; } } return 0; }
以上是关于[Luogu] 魔法树的主要内容,如果未能解决你的问题,请参考以下文章