题目大意:有一棵树,两个修改
- $install;x:$把根节点到$x$软件路径上的值全部变为$1$,并输出修改的节点个数
- $uninstall;x:$把$x$以及它的子树的值变为$0$,并输出修改的节点个数
题解:树链剖分,比较一下修改前后值的变化,即为答案
卡点:1.边忘记开两倍
C++ Code:
#include <cstdio> #define maxn 100010 using namespace std; int n, m; int head[maxn], cnt; struct Edge { int to, nxt; } e[maxn << 1]; void add(int a, int b) { e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt; } int dep[maxn], sz[maxn], fa[maxn]; int dfn[maxn], son[maxn], top[maxn], idx; void dfs1(int rt) { sz[rt] = 1; for (int i = head[rt]; i; i = e[i].nxt) { int v = e[i].to; if (v != fa[rt]) { fa[v] = rt; dep[v] = dep[rt] + 1; dfs1(v); sz[rt] += sz[v]; if (!son[rt] || sz[son[rt]] < sz[v]) son[rt] = v; } } } void dfs2(int rt) { dfn[rt] = ++idx; int v = son[rt]; if (v) top[v] = top[rt], dfs2(v); for (int i = head[rt]; i; i = e[i].nxt) { v = e[i].to; if (v != fa[rt] && v != son[rt]) { top[v] = v; dfs2(v); } } } int V[maxn << 2]; void add(int rt, int l, int r, int L, int R, int op) { if (L <= l && R >= r) { V[rt] = (r - l + 1) * op; return ; } if (V[rt] == r - l + 1) { V[rt << 1] = r - l + 2 >> 1; V[rt << 1 | 1] = r - l + 1 >> 1; } int mid = l + r >> 1; if (L <= mid) add(rt << 1, l, mid, L, R, op); if (R > mid) add(rt << 1 | 1, mid + 1, r, L, R, op); V[rt] = V[rt << 1] + V[rt << 1 | 1]; } int ask(int rt, int l, int r, int L, int R) { if (L <= l && R >= r) return V[rt]; if (V[rt] == r - l + 1) { V[rt << 1] = r - l + 2 >> 1; V[rt << 1 | 1] = r - l + 1 >> 1; } if (V[rt] == 0) V[rt << 1] = V[rt << 1 | 1] = 0; int mid = l + r >> 1, ans = 0; if (L <= mid) ans = ask(rt << 1, l, mid, L, R); if (R > mid) ans += ask(rt << 1 | 1, mid + 1, r, L, R); return ans; } inline void swap(int &a, int &b) {a ^= b ^= a ^= b;} void modify(int x, int y, int num) { while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); add(1, 1, n, dfn[top[x]], dfn[x], num); x = fa[top[x]]; } if (dep[x] > dep[y]) swap(x, y); add(1, 1, n, dfn[x], dfn[y], num); } int query(int x, int y) { int ans = 0; while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); ans += ask(1, 1, n, dfn[top[x]], dfn[x]); x = fa[top[x]]; } if (dep[x] > dep[y]) swap(x, y); ans += ask(1, 1, n, dfn[x], dfn[y]); return ans; } int root = 1; int main() { scanf("%d", &n); for (int i = 1; i < n; i++) { int a; scanf("%d", &a); add(a + root, i + root); add(i + root, a + root); } dep[top[root] = root] = 1; dfs1(root); dfs2(root); scanf("%d", &m); while (m --> 0) { char op[15]; int ans, x; scanf("%s%d", op, &x); x += root; if (op[0] == 'i') { ans = query(root, x); modify(root, x, 1); printf("%d ", query(root, x) - ans); } else { ans = ask(1, 1, n, dfn[x], dfn[x] + sz[x] - 1); add(1, 1, n, dfn[x], dfn[x] + sz[x] - 1, 0); printf("%d ", ans - ask(1, 1, n, dfn[x], dfn[x] + sz[x] - 1)); } } return 0; }