题解:
首先我们观察到0号不会依赖别人,而其他的软件都会依赖且仅会依赖一个软件。因此这是一棵树。
于是我们在看看要支持一些什么操作。
1,安装一个软件要改变多少软件的状态。
如果将一个软件与所依赖的软件相连,那么可能要改变的状态就是它自己和往上走直到根的那条链上的点。
2,卸载一个软件要改变多少软件的状态
显然是自己+子树。
那么我们可以想到什么呢?
树链剖分!
安装就查询从自己往上走的点中有多少已经被安装。
deep[x](deep[0] = 1)就是可能要改变的软件数,假设已经有k个被安装,那么要改变的软件数就是deep[x] - k
卸载就查询子树+自己中有多少已经安装了的,这个数量就是答案。
每次安装查询时都把查询的点赋为1,卸载时把所有涉及到的点赋为0,线段树维护
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define R register int 4 #define AC 120000 5 #define ac 600000//error ...所以说还是数组小了的锅么 6 #define D printf("line in %d ", __LINE__); 7 int n, m, cnt, ans, w; 8 int date[AC], Next[AC], Head[AC], tot;//因为是树,所以只要开这么大 9 int son[AC], top[AC], father[AC], deep[AC], Size[AC], id[AC]; 10 int tree[ac], l[ac], r[ac], lazy[ac];//线段树开4倍吧 11 char s[30]; 12 13 inline int read() 14 { 15 int x = 0; char c = getchar(); 16 while(c > '9' || c < '0') c = getchar(); 17 while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();//error !!! 读入优化写错了。。。。 18 return x; 19 } 20 21 inline void add(int f, int w) 22 { 23 date[++tot] = w, Next[tot] = Head[f], Head[f] = tot; 24 } 25 26 void pre()//读入依赖关系, 因为编号从0开始, 所以整体往后顺延一个 27 { 28 n = read();//序号全部往后推一个, 但总数又不会变,,,, 29 for(R i=2;i<=n;i++) 30 { 31 father[i] = read() + 1; 32 add(father[i], i); 33 } 34 deep[1] = 1; 35 } 36 //Size包括自己 37 void dfs1(int x)//get son && Size && deep 38 { 39 int maxson = 0, now; 40 Size[x] = 1;//先加上自己 41 for(R i = Head[x]; i ; i = Next[i]) 42 { 43 now = date[i]; 44 if(now == father[x]) continue; 45 deep[now] = deep[x] + 1; 46 dfs1(now); 47 Size[x] += Size[now]; 48 if(Size[now] > Size[maxson]) maxson = now; 49 } 50 son[x] = maxson; 51 } 52 53 void dfs2(int x, int topx)//get top && id 54 { 55 int now; 56 id[x] = ++cnt; 57 top[x] = topx; 58 if(!son[x]) return ; 59 dfs2(son[x], topx);//继承top 60 for(R i = Head[x]; i ; i = Next[i]) 61 { 62 now = date[i]; 63 if(now == father[x] || now == son[x]) continue;//这两个都是不能去的 64 dfs2(now, now);//新开 65 } 66 } 67 68 void build(int x, int ll, int rr) 69 { 70 l[x] = ll, r[x] = rr; 71 if(ll == rr) return ;//...调试没删 72 int mid = (ll + rr) >> 1; 73 build(x * 2, ll, mid); 74 build(x * 2 + 1, mid + 1, rr); 75 } 76 77 inline void update(int x) 78 { 79 int ll = x * 2, rr = ll + 1; 80 lazy[ll] = lazy[rr] = lazy[x]; 81 tree[ll] = (r[ll] - l[ll] + 1) * (lazy[x] - 1);//要么全为0,要么全为1 82 tree[rr] = (r[rr] - l[rr] + 1) * (lazy[x] - 1);//为了方便判断 83 lazy[x] = 0;//下传标记之后要清0 84 }//1 表示 0, 2 表示1,所以用的时候要-1 85 86 void search(int x, int ll, int rr) 87 { 88 if(lazy[x]) update(x); 89 if(ll == l[x] && rr == r[x]) 90 { 91 ans -= tree[x]; 92 return ; 93 } 94 else 95 { 96 int mid = (l[x] + r[x]) >> 1; 97 if(ll > mid) search(x * 2 + 1, ll, rr); 98 else if(rr <= mid) search(x * 2, ll, rr); 99 else 100 { 101 search(x * 2, ll, mid); 102 search(x * 2 + 1, mid + 1, rr); 103 } 104 } 105 } 106 107 void change(int x, int ll, int rr) 108 { 109 if(l[x] == ll && r[x] == rr) 110 { 111 lazy[x] = w; 112 tree[x] = (r[x] - l[x] + 1) * (w - 1); 113 } 114 else 115 { 116 int mid = (l[x] + r[x]) >> 1; 117 if(ll > mid) change(x * 2 + 1, ll, rr); 118 else if(rr <= mid) change(x * 2, ll, rr); 119 else 120 { 121 change(x * 2, ll, mid); 122 change(x * 2 + 1, mid + 1, rr); 123 } 124 tree[x] = tree[x * 2] + tree[x * 2 + 1];//因为是直接修改,而不是加减,所以在这里修改tree[x]的值 125 } 126 } 127 128 void install(int x) 129 { 130 ans = deep[x]; 131 w = 2;//改为1(这里2代表1) 132 while(x)//father[top[1]] = 0; 133 { 134 search(1, id[top[x]], id[x]); 135 change(1, id[top[x]], id[x]); 136 x = father[top[x]]; 137 } 138 printf("%d ", ans); 139 } 140 141 void uninstall(int x) 142 { 143 ans = 0; 144 search(1, id[x], id[x] + Size[x] - 1); 145 w = 1; 146 change(1, id[x], id[x] + Size[x] - 1); 147 printf("%d ", -ans);//因为默认是减,所以直接求的话会是相反数 148 } 149 150 void work()//读入询问 151 { 152 int a; 153 m = read(); 154 //scanf("%d", &m); 155 for(R i = 1; i <= m; i++) 156 { 157 scanf("%s", s + 1); 158 // printf("%d: ", i); 159 // printf("%d ", l[7424]); 160 //b = i;//辅助watch 161 a = read() + 1; 162 if(s[1] == 'i') install(a);//安装 163 else uninstall(a); 164 } 165 } 166 167 int main() 168 { 169 // freopen("in.in", "r", stdin); 170 pre(); 171 dfs1(1); 172 dfs2(1, 1); 173 build(1, 1, n); 174 work(); 175 // fclose(stdin); 176 return 0; 177 }