树链剖分
先粘模板, 然后再粘一个入门题的代码.
#include <cstdio> #include <algorithm> #define lson rt<<1 #define rson rt<<1|1 using namespace std; typedef long long ll; const ll maxn = 1e5+500; int qsz, qcnt; ll date[maxn]; int head[maxn]; int deep[maxn]; int size[maxn]; int top[maxn]; // 重链的起点. int son[maxn]; int id[maxn]; // 节点u的dfs序号 int rk[maxn]; // dfs序号为i的节点 如果使用线段树之类的, build里应该使用 rk int pa[maxn]; // 父节点 // First dfs is aim to getting son[], size[] and deep[] pa[] int dfs(int u, int fa) { int i, v, sz = 1, t1; deep[u] = deep[fa] + 1; son[u] = u; size[u] = 0; pa[u] = fa; for (i=head[u]; i; i=edge[i].lst) { v = edge[i].to; if (v == fa) continue; t1 = dfs(v, u); sz += t1; if (size[son[u]] < t1) son[u] = v; } size[u] = sz; return sz; } // Second dfs is aim to getting id[] rk[] top[] void dfs2(int u, int fa, int t) { int i, v; top[u] = t; id[u] = qcnt; rk[qcnt++] = u; // update top[] id[] rk[] if (son[u] != u) dfs2(son[u], u, t); for (i=head[u]; i; i=edge[i].lst) { v = edge[i].to; if (v == fa || son[u] == v) continue; dfs2(v, u, v); // 轻儿子 top is itself. } } ll op(int x, int y) { int fx = top[x], fy = top[y]; ll res = 0; while (fx != fy) { // 比较top的深度 来选择那个节点需要移动 // 选择深度比较深的节点向上移动. // 这儿定义 fy的深度比较深 if (deep[fx] > deep[fy]) { swap(fx, fy); swap(x, y); } res = (res + query(id[fy], id[y], 1)); // query()是你维护方式, 这儿用的线段树维护. y = pa[fy]; // 这条top链已经获取好信息了, 所以应该是 pa[fy] fy = top[y]; // 继续走 } // 最后 fx fy在同一条链上. dfs序深度浅的小, 深度深的大. if (id[x] <= id[y]) res += query(id[x], id[y], 1); else res += query(id[y], id[x], 1); return res; } // 树链剖分要修改某一棵子树, 就是修改这段区间[id[x], id[x]+size[x]-1] 注,size[x]包含x节点. int main() { // init qsz = 1; qcnt = 1; deep[0] = 0; dfs(1, 0); dfs2(1, 0, 1); return 0; }
入门题 HYSBZ - 4034
#include <cstdio> #include <algorithm> #define lson rt<<1 #define rson rt<<1|1 using namespace std; typedef long long ll; const ll maxn = 1e5+500; int qsz, qcnt; ll date[maxn]; int head[maxn]; int deep[maxn]; int size[maxn]; int top[maxn]; int son[maxn]; int id[maxn]; // ½ÚµãuµÄdfsÐò int rk[maxn]; // dfsΪiµÄ½Úµã int pa[maxn]; // ½ÚµãuµÄ¸¸½Úµã struct nobe { int to; int lst; }edge[maxn<<1]; inline void add(int u, int v) { edge[qsz].to = v; edge[qsz].lst = head[u]; head[u] = qsz++; } // First dfs is aim to getting son[], size[] and deep[] pa[] int dfs(int u, int fa) { int i, v, sz = 1, t1; deep[u] = deep[fa] + 1; son[u] = u; size[u] = 0; pa[u] = fa; for (i=head[u]; i; i=edge[i].lst) { v = edge[i].to; if (v == fa) continue; t1 = dfs(v, u); sz += t1; if (size[son[u]] < t1) son[u] = v; } size[u] = sz; return sz; } // Second dfs is aim to getting id[] rk[] top[] void dfs2(int u, int fa, int t) { int i, v; top[u] = t; id[u] = qcnt; rk[qcnt++] = u; // update top[] id[] rk[] if (son[u] != u) dfs2(son[u], u, t); for (i=head[u]; i; i=edge[i].lst) { v = edge[i].to; if (v == fa || son[u] == v) continue; dfs2(v, u, v); // ~~~link top is itself. } } struct nobe2 { int l; int r; ll val; ll lazy; void fun(ll jval) { val += jval * (r - l + 1); lazy += jval; } }te[maxn<<2]; inline void pshup(int rt) { te[rt].val = te[lson].val + te[rson].val; } void build(int l, int r, int rt) { te[rt].l = l; te[rt].r = r; te[rt].lazy = 0; if (l == r) { te[rt].val = date[rk[l]]; // rk[l] return ; } int m = (l + r) >> 1; build(l, m, lson); build(m+1, r, rson); pshup(rt); } inline void pshdwn(int rt) { if (te[rt].lazy) { te[lson].fun(te[rt].lazy); te[rson].fun(te[rt].lazy); te[rt].lazy = 0; } } void update(int l, int r, ll val, int rt) { if (l>te[rt].r || r<te[rt].l) return ; if (l<=te[rt].l && r>=te[rt].r) { te[rt].fun(val); return ; } pshdwn(rt); update(l, r, val, lson); update(l, r, val, rson); pshup(rt); } ll query(int l, int r, int rt) { if (l>te[rt].r || r<te[rt].l) return 0; if (l<=te[rt].l && r>=te[rt].r) return te[rt].val; pshdwn(rt); return (query(l, r, lson) + query(l, r, rson)); } ll op2(int x, int y) { int fx = top[x], fy = top[y]; ll res = 0; while (fx != fy) { if (deep[fx] > deep[fy]) { swap(fx, fy); swap(x, y); } res = (res + query(id[fy], id[y], 1)); y = pa[fy]; fy = top[y]; } if (id[x] <= id[y]) res += query(id[x], id[y], 1); else res += query(id[y], id[x], 1); return res; } void op3(int x, ll z) { update(id[x], id[x] + size[x] - 1, z, 1); } int main() { int n, m; int i, j, u, v, op, x, y; ll z; // init qsz = 1; qcnt = 1; scanf("%d%d", &n, &m); for (i=1; i<=n; ++i) scanf("%lld", date+i); for (i=1; i<n; ++i) { scanf("%d%d", &u, &v); add(u, v); add(v, u); } deep[0] = 0; dfs(1, 0); dfs2(1, 0, 1); build(1, n, 1); while (m--) { scanf("%d", &op); switch (op) { case 1: scanf("%d%lld", &x, &z); update(id[x], id[x], z, 1); break; case 2: scanf("%d%lld", &x, &z); op3(x, z); break; case 3: scanf("%d", &x); printf("%lld\n", op2(1, x)); break; } } return 0; }