【NOI 2015】软件包管理器
【题目链接】
【算法】
树链剖分,子树的DFS序也是连续的一段
要注意细节!
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 100000 struct SegmentTree { int l,r,sum[2],opt; } tree[MAXN*3]; int i,N,Q,x,num; int depth[MAXN+10],size[MAXN+10],son[MAXN+10],fa[MAXN+10], top[MAXN+10],id[MAXN+10]; string type; vector<int> E[MAXN+10]; template <typename T> inline void read(T &x) { int f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; } for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> inline void write(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) write(x/10); putchar(x%10+'0'); } template <typename T> inline void writeln(T x) { write(x); puts(""); } inline void dfs1(int x) { int i,y; size[x] = 1; for (i = 0; i < E[x].size(); i++) { y = E[x][i]; if (y != fa[x]) { fa[y] = x; depth[y] = depth[x] + 1; dfs1(y); size[x] += size[y]; if ((size[y] > size[son[x]]) || (!son[x])) son[x] = y; } } } inline void dfs2(int x,int tp) { int i,y; top[x] = tp; id[x] = ++num; if (son[x]) dfs2(son[x],tp); for (i = 0; i < E[x].size(); i++) { y = E[x][i]; if ((y != fa[x]) && (y != son[x])) dfs2(y,y); } } inline void build(int index,int l,int r) { int mid; tree[index].l = l; tree[index].r = r; tree[index].opt = 0; tree[index].sum[0] = r - l + 1; if (l == r) return; mid = (l + r) >> 1; build(index*2,l,mid); build(index*2+1,mid+1,r); } inline void pushdown(int index) { if (tree[index].l == tree[index].r) return; tree[index*2].opt = tree[index].opt; tree[index*2].sum[tree[index].opt] = tree[index*2].r - tree[index*2].l + 1; tree[index*2].sum[tree[index].opt^1] = 0; tree[index*2+1].opt = tree[index].opt; tree[index*2+1].sum[tree[index].opt] = tree[index*2+1].r - tree[index*2+1].l + 1; tree[index*2+1].sum[tree[index].opt^1] = 0; } inline void pushup(int index) { tree[index].sum[0] = tree[index*2].sum[0] + tree[index*2+1].sum[0]; tree[index].sum[1] = tree[index*2].sum[1] + tree[index*2+1].sum[1]; if (tree[index*2].opt != tree[index*2+1].opt) { tree[index].opt = -1; return; } if ((tree[index*2].opt == -1) || (tree[index*2+1].opt == -1)) { tree[index].opt = -1; return; } tree[index].opt = tree[index*2].opt; } void modify(int index,int l,int r,int val) { int mid; if (tree[index].opt != -1) pushdown(index); if ((tree[index].l == l) && (tree[index].r == r)) { tree[index].sum[val] = r - l + 1; tree[index].sum[val^1] = 0; tree[index].opt = val; } else { mid = (tree[index].l + tree[index].r) >> 1; if (mid >= r) modify(index*2,l,r,val); else if (mid + 1 <= l) modify(index*2+1,l,r,val); else { modify(index*2,l,mid,val); modify(index*2+1,mid+1,r,val); } pushup(index); } } inline int query(int index,int l,int r,int val) { int mid; if (tree[index].opt != -1) pushdown(index); if ((tree[index].l == l) && (tree[index].r == r)) return tree[index].sum[val]; else { mid = (tree[index].l + tree[index].r) >> 1; if (mid >= r) return query(index*2,l,r,val); else if (mid + 1 <= l) return query(index*2+1,l,r,val); else return query(index*2,l,mid,val) + query(index*2+1,mid+1,r,val); } } inline int Install(int x) { int tp = top[x], ans = 0; while (tp) { ans += query(1,id[tp],id[x],0); modify(1,id[tp],id[x],1); x = fa[tp]; tp = top[x]; } ans += query(1,1,id[x],0); modify(1,1,id[x],1); return ans; } inline int Uninstall(int x) { int ans = query(1,id[x],id[x]+size[x]-1,1); modify(1,id[x],id[x]+size[x]-1,0); return ans; } int main() { read(N); for (i = 1; i < N; i++) { read(x); E[x].push_back(i); } depth[0] = 1; dfs1(0); dfs2(0,0); build(1,1,num); read(Q); while (Q--) { cin >> type; if (type == "install") { read(x); writeln(Install(x)); } else { read(x); writeln(Uninstall(x)); } } return 0; }