Luogu 4216 [SCOI2015]情报传递
BZOJ 4448。
写起来很愉悦的题。
按照时间可持久化线段树,修改就在原来的地方加$1$即可,查询就直接询问$root_1 - root_{now - c - 1}$中相应的个数。
主席树维护树链剖分即可。
时间复杂度$O(nlog^2n)$。
Code:
#include <cstdio> #include <cstring> using namespace std; const int N = 2e5 + 5; int n, rt, qn, tot = 0, head[N]; int dfsc = 0, id[N], siz[N], fa[N], top[N], son[N], dep[N]; struct Edge { int to, nxt; } e[N << 1]; inline void add(int from, int to) { e[++tot].to = to; e[tot].nxt = head[from]; head[from] = tot; } inline void read(int &X) { X = 0; char ch = 0; int op = 1; for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') op = -1; for(; ch >= '0' && ch <= '9'; ch = getchar()) X = (X << 3) + (X << 1) + ch - 48; X *= op; } inline void swap(int &x, int &y) { int t = x; x = y; y = t; } void dfs1(int x, int fat, int depth) { fa[x] = fat, dep[x] = depth, siz[x] = 1; int maxson = -1; for(int i = head[x]; i; i = e[i].nxt) { int y = e[i].to; if(y == fat) continue; dfs1(y, x, depth + 1); siz[x] += siz[y]; if(siz[y] > maxson) { son[x] = y; maxson = siz[y]; } } } void dfs2(int x, int topf) { top[x] = topf, id[x] = ++dfsc; if(!son[x]) return; dfs2(son[x], topf); for(int i = head[x]; i; i = e[i].nxt) { int y = e[i].to; if(y == fa[x] || y == son[x]) continue; dfs2(y, y); } } namespace PSegT { struct Node { int lc, rc, sum; } s[N * 40]; int root[N], nodeCnt = 0; #define lc(p) s[p].lc #define rc(p) s[p].rc #define mid ((l + r) >> 1) #define sum(p) s[p].sum void ins(int &p, int l, int r, int x, int pre) { s[p = ++nodeCnt] = s[pre]; ++sum(p); if(l == r) return; if(x <= mid) ins(lc(p), l, mid, x, lc(pre)); else ins(rc(p), mid + 1, r, x, rc(pre)); } int query(int r1, int r2, int l, int r, int x, int y) { if(x <= l && y >= r) return sum(r2) - sum(r1); int res = 0; if(x <= mid) res += query(lc(r1), lc(r2), l, mid, x, y); if(y > mid) res += query(rc(r1), rc(r2), mid + 1, r, x, y); return res; } } using namespace PSegT; inline void solve(int r) { int x, y, c, res = 0; read(x), read(y), read(c); r -= c + 1; int px = x, py = y; for(; top[x] != top[y]; ) { if(dep[top[x]] < dep[top[y]]) swap(x, y); if(r > 0) res += query(root[0], root[r], 1, n, id[top[x]], id[x]); x = fa[top[x]]; } if(dep[x] > dep[y]) swap(x, y); if(r > 0) res += query(root[0], root[r], 1, n, id[x], id[y]); printf("%d %d\n", dep[px] + dep[py] - 2 * dep[x] + 1, res); } int main() { read(n); for(int fat, i = 1; i <= n; i++) { read(fat); if(!fat) rt = i; else add(i, fat), add(fat, i); } dfs1(rt, 0, 1), dfs2(rt, rt); read(qn); for(int op, i = 1; i <= qn; i++) { root[i] = root[i - 1]; read(op); if(op == 2) { int x; read(x); ins(root[i], 1, n, id[x], root[i]); } else solve(i); } return 0; }