题意:
给出一棵树,做 M 次操作,每次要么将一棵子树上每个结点的布尔值取反,要么查询一棵子树上布尔值为 true 的个数
思路:
给一颗树,怎么得到它的dfs序
为什么可以这样呢
设定a[i]存dfs序为i的节点,L[i]是i的子树中dfs序最小的,R[i]是i的子树中dfs序最大的
因为对任意一个节点x, 子树的范围就是L[x]-R[x]
子树转化成线段,线段转化成子树。。
这样就可以用线段树+lazy来解决了
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i, s, t) for(int (i)=(s);(i)<=(t);++(i))
template<class T>
void d_print(const T& vec) {
copy( vec.begin(), vec.end(), ostream_iterator<int>(cout, " ") ); cout << endl;
}
const int N = 100100;
vector<int> g[N+1];
int countor = 0, lef[N+1], rig[N+1];
void get_tag(int x) {
lef[x] = ++ countor;
for (int i = 0; i < g[x].size(); ++i)
get_tag(g[x][i]);
rig[x] = countor;
}
int sum[N*4], mk[N*4];
#define lc o<<1
#define rc o<<1|1
void upd(int o, int len) {
mk[o] ^= 1;
sum[o] = len - sum[o];
}
void push(int o, int len) {
if ( mk[o] ) {
upd(lc, len - len/2); upd(rc, len/2);
mk[o] = 0;
}
}
void modify(int o, int l, int r, int qL, int qR) {
int len = r - l + 1;
if ( l >= qL && r <= qR ) {
upd(o, len); return;
}
push(o, len);
int mid = (l+r)/2;
if ( qL <= mid )
modify(lc, l, mid, qL, qR);
if ( qR > mid )
modify(rc, mid+1, r, qL, qR);
sum[o] = sum[lc] + sum[rc];
}
int query(int o, int l, int r, int qL, int qR) {
if ( l >= qL && r <= qR ) {
//cout << "ask " << l << ' ' << r << ' ' << sum[o] << endl;
return sum[o];
}
push(o, r - l + 1);
int mid = (l+r)/2, ret = 0;
if ( qL <= mid )
ret += query(lc, l, mid, qL, qR);
if ( qR > mid )
ret += query(rc, mid+1, r, qL, qR);
//cout << "ask " << l << ' ' << r << ' ' << ret << endl;
return ret;
}
int main() {
#ifdef _LOCA_ENV_
freopen("input.in", "r", stdin);
#endif // _LOCA_ENV
int n, m;
while ( scanf("%d%d", &n, &m) != EOF ) {
rep(i, 1, n) g[i].clear();
rep(i, 2, n) {
int x; scanf("%d", &x);
g[x].push_back(i);
}
countor = 0;
get_tag(1);
memset(sum, 0, sizeof(sum));
memset(mk, 0, sizeof(mk));
char buf[64];
int x;
rep(i, 1, m) {
scanf("%s%d", buf, &x);
//cout << op << ' ' << x << endl;
if ( buf[0] == 'o' ) {
modify(1, 1, n, lef[x], rig[x]);
} else {
int tmp = query(1, 1, n, lef[x], rig[x]);
printf("%d\n", tmp);
}
}
puts("");
}
return 0;
}