这明显就是一道树剖的水题~~~
install操作就是查询x到根节点的路径中0的个数,并且每一个节点的权值都改成1.
uninstall就是查询x的子树中1的个数,并都改成0.
有一个优化就是install操作中如果当前区间已经有1了,就可以不用往上查,直接返回。因为从题中可以得到一个信息,如果有一个点的权值是1,那么他祖先的所有节点一定都是1。
嗯,完了。
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 1e5 + 5; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), last = ' '; 25 while(!isdigit(ch)) {last = ch; ch = getchar();} 26 while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();} 27 if(last == '-') ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) x = -x, putchar('-'); 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + '0'); 35 } 36 37 int n, m; 38 vector<int> v[maxn]; 39 40 int dep[maxn], fa[maxn], siz[maxn], son[maxn]; 41 void dfs1(int now) 42 { 43 siz[now] = 1; 44 for(int i = 0; i < (int)v[now].size(); ++i) 45 { 46 dep[v[now][i]] = dep[now] + 1; 47 fa[v[now][i]] = now; 48 dfs1(v[now][i]); 49 siz[now] += siz[v[now][i]]; 50 if(!son[now] || siz[son[now]] < siz[v[now][i]]) son[now] = v[now][i]; 51 } 52 } 53 int dfsx[maxn], pos[maxn], top[maxn], cnt = 0; 54 void dfs2(int now) 55 { 56 dfsx[now] = ++cnt; pos[cnt] = now; 57 if(son[now]) 58 { 59 top[son[now]] = top[now]; 60 dfs2(son[now]); 61 } 62 for(int i = 0; i < (int)v[now].size(); ++i) 63 { 64 if(v[now][i] != son[now]) 65 { 66 top[v[now][i]] = v[now][i]; 67 dfs2(v[now][i]); 68 } 69 } 70 } 71 72 int l[maxn << 2], r[maxn << 2], sum[maxn << 2], lzy[maxn << 2]; 73 void build(int L, int R, int now) 74 { 75 l[now] = L; r[now] = R; 76 lzy[now] = -1; 77 if(L == R) return; 78 int mid = (L + R) >> 1; 79 build(L, mid, now << 1); 80 build(mid + 1, R, now << 1 | 1); 81 } 82 void pushdown(int now) 83 { 84 if(lzy[now] != -1) 85 { 86 sum[now << 1] = (r[now << 1] - l[now << 1] + 1) * lzy[now]; 87 sum[now << 1 | 1] = (r[now << 1 | 1] - l[now << 1 | 1] + 1) * lzy[now]; 88 lzy[now << 1] = lzy[now << 1 | 1] = lzy[now]; 89 lzy[now] = -1; 90 } 91 } 92 void update(int L, int R, int now, bool flg) 93 { 94 if(L == l[now] && R == r[now]) 95 { 96 sum[now] = (R - L + 1) * flg; 97 lzy[now] = flg; return; 98 } 99 pushdown(now); 100 int mid = (l[now] + r[now]) >> 1; 101 if(R <= mid) update(L, R, now << 1, flg); 102 else if(L > mid) update(L, R, now << 1 | 1, flg); 103 else update(L, mid, now << 1, flg), update(mid + 1, R, now << 1 | 1, flg); 104 sum[now] = sum[now << 1] + sum[now << 1 | 1]; 105 } 106 int query(int L, int R, int now) 107 { 108 if(L == l[now] && R == r[now]) return sum[now]; 109 pushdown(now); 110 int mid = (l[now] + r[now]) >> 1; 111 if(R <= mid) return query(L, R, now << 1); 112 else if(L > mid) return query(L, R, now << 1 | 1); 113 else return query(L, mid, now << 1) + query(mid + 1, R, now << 1 | 1); 114 } 115 116 int query_in(int x) 117 { 118 int ret = 0; 119 bool flg = 1; 120 while(top[x] != top[1]) 121 { 122 int tp = query(dfsx[top[x]], dfsx[x], 1); 123 ret += dfsx[x] - dfsx[top[x]] + 1 - tp; 124 update(dfsx[top[x]], dfsx[x], 1, 1); 125 if(tp) {flg = 0; break;} 126 x = fa[top[x]]; 127 } 128 if(!flg) return ret; 129 ret += dfsx[x] - dfsx[1] + 1 - query(dfsx[1], dfsx[x], 1); 130 update(dfsx[1], dfsx[x], 1, 1); 131 return ret; 132 } 133 int query_un(int x) 134 { 135 int ret = query(dfsx[x], dfsx[x] + siz[x] - 1, 1); 136 update(dfsx[x], dfsx[x] + siz[x] - 1, 1, 0); 137 return ret; 138 } 139 140 char c[12]; 141 142 int main() 143 { 144 n = read(); 145 for(int i = 2; i <= n; ++i) 146 { 147 int x = read() + 1; 148 v[x].push_back(i); 149 } 150 dfs1(1); top[1] = 1; dfs2(1); 151 build(1, cnt, 1); 152 m = read(); 153 for(int i = 1; i <= m; ++i) 154 { 155 scanf("%s", c); int x = read() + 1; 156 if(c[0] == 'i') write(query_in(x)), enter; 157 else write(query_un(x)), enter; 158 } 159 return 0; 160 }