正题
luogu 2146
金牌导航 树链剖分-2
题目大意
有若干软件,除了软件0,所有软件都依赖且只依赖于另外一个软件
当要删除一个软件时,所有依赖于该软件的软件都要删掉
当安装一个软件时,该软件依赖的软件都要安装
问你每次操作会影响多少个软件
解题思路
依赖连边会形成一棵树,
每次删除搜索子树,每次安装搜索到根节点的路径
到根节点的路径用树剖处理即可
代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define N 100010
using namespace std;
int n, x, w, q, tot;
int v[N], fa[N], sz[N], ed[N], hs[N], anc[N], dep[N], head[N];
char str[100];
struct rec {int to, next;
} a[N];
void add(int x, int y) {a[++tot].to = y;a[tot].next = head[x];head[x] = tot;
}
struct Tree {
#define ls x * 2
#define rs x * 2 + 1int p[N << 2], s[N << 2], lazy[N << 2];void build(int x, int l, int r) {lazy[x] = -1;if (l == r)return;int mid = l + r >> 1;build(ls, l, mid);build(rs, mid + 1, r);return;}void up(int x) {s[x] = s[ls] + s[rs];return;}void down(int x, int l, int r) {if (lazy[x] != -1) {if (l < r) {int mid = l + r >> 1;lazy[ls] = lazy[rs] = lazy[x];s[ls] = lazy[x] * (mid - l + 1);s[rs] = lazy[x] * (r - mid);}lazy[x] = -1;}return;}void change(int x, int L, int R, int l, int r, int y) {if (L == l && R == r) {lazy[x] = y;s[x] = y * (r - l + 1);return;}down(x, L, R);int mid = L + R >> 1;if (r <= mid)change(ls, L, mid, l, r, y);else if (l > mid)change(rs, mid + 1, R, l, r, y);elsechange(ls, L, mid, l, mid, y), change(rs, mid + 1, R, mid + 1, r, y);up(x);}int ask(int x, int L, int R, int l, int r) {if (L == l && R == r)return s[x];down(x, L, R);int mid = L + R >> 1;if (r <= mid)return ask(ls, L, mid, l, r);else if (l > mid)return ask(rs, mid + 1, R, l, r);elsereturn ask(ls, L, mid, l, mid) + ask(rs, mid + 1, R, mid + 1, r);}
} T;
void dfs1(int x) {sz[x] = 1;for (int i = head[x]; i; i = a[i].next) {dep[a[i].to] = dep[x] + 1;fa[a[i].to] = x;dfs1(a[i].to);sz[x] += sz[a[i].to];if (sz[a[i].to] > sz[hs[x]])hs[x] = a[i].to;}return;
}
void dfs2(int x, int y) {anc[x] = y;v[x] = ++w;if (hs[x])dfs2(hs[x], y);for (int i = head[x]; i; i = a[i].next)if (a[i].to != hs[x])dfs2(a[i].to, a[i].to);ed[x] = w;
}
int solve(int x) {//到根节点的路径int sum = 0;while (anc[x] != 1) {sum += dep[x] - dep[anc[x]] + 1 - T.ask(1, 1, n, v[anc[x]], v[x]);T.change(1, 1, n, v[anc[x]], v[x], 1);x = fa[anc[x]];}sum += dep[x] - dep[anc[x]] + 1 - T.ask(1, 1, n, v[anc[x]], v[x]);T.change(1, 1, n, v[anc[x]], v[x], 1);return sum;
}
int solve2(int x) {//子树int sum = T.ask(1, 1, n, v[x], ed[x]);T.change(1, 1, n, v[x], ed[x], 0);return sum;
}
int main() {scanf("%d", &n);for (int i = 2; i <= n; ++i) {scanf("%d", &x);x++;add(x, i);}dfs1(1);dfs2(1, 1);scanf("%d", &q);while (q--) {scanf("%s%d", str + 1, &x);x++;if (str[1] == 'i')printf("%d\n", solve(x));elseprintf("%d\n", solve2(x));}return 0;
}