https://www.luogu.org/problemnew/show/P2146 传送门
简单的树链剖分......维护下当前安装了多少个包......修改后查询下就行了......附上极其丑陋的代码......
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; ; int head[N], to[N], v[N], p; void build(int a, int b) { v[++ p] = b; to[p] = head[a]; head[a] = p; } #define mid (l + r >> 1) ], lazy[N << ]; void push_down(int c, int l, int r) { if( !lazy[c]) return ; lazy[c] --; tr[c << ] = (mid - l + ) * lazy[c]; tr[c << |] = (r - mid) * lazy[c]; lazy[c << ] = lazy[c << |] = lazy[c] + ; lazy[c] = ; } void change(int c, int l, int r, int L, int R, int o) { if( L <= l && R >= r) { tr[c] = (r - l + ) * o; lazy[c] = o + ; return ; } push_down(c, l, r); , l, mid, L, R, o); |, mid+, r, L, R, o); tr[c] = tr[c << ] + tr[c << |]; } int get_(int c, int l, int r, int L, int R) { if( l == L && R == r) return tr[c]; push_down(c, l, r); , l, mid, L, R); |, mid+, r, L, R); , l, mid, L, mid) + get_(c << |, mid+, r, mid+, R); } int son[N], si[N]; void search(int u) { si[u] = ; son[u] = ; for( int i = head[u]; ~i; i = to[i]) { search(v[i]), si[u] += si[v[i]]; if( si[v[i]] > si[son[u]]) son[u] = v[i]; } } int top[N], dfs[N], dfn[N], cnt; void build_son(int u, int c) { top[u] = c; dfs[u] = ++cnt; if( son[u]) build_son(son[u], c); for( int i = head[u]; ~i; i = to[i]) if( v[i] != son[u]) build_son(v[i], v[i]); dfn[u] = cnt; } int n, q, pre[N]; void query(int a) { ]; while( a) { change(, , n, dfs[top[a]], dfs[a], ); a = pre[top[a]]; }printf(] - tcmp); } ]; int main() { scanf(, ; ; i <= n; i ++) scanf("%d", pre + i), pre[i] ++ ; ; i <= n; i ++) build(pre[i], i); search();build_son(, ); scanf("%d", &q); , a; i <= q; i ++) { scanf("%s%d", s, &a); a ++; ] == 'i') query(a); else { ]; change(, , n, dfs[a], dfn[a], ); printf(]); } } }