Description
给你一棵树, 每个节点都是一盏灯,有开和关的状态,有两种操作:
1、查询以u为根节点的子树,有多少个节点(包括根节点)亮着。
2、更改以u为根节点的子树,亮->暗,暗->亮(包括根节点)亮着。
Solution
先用dfs序将树处理成线段树可以维护的状态, 然后线段树维护即可。
push_up里面没有写push_down,调了半天。。。
时间复杂度:求dfs序O(n),维护线段树O(logn)
Code
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int n, m;
int idx, in[N], out[N];
vector<int> g[N];
void dfs(int u, int fa) {
in[u] = ++idx;
for(int i = 0; i < g[u].size(); ++i) {
int v = g[u][i];
if(v == fa) continue;
dfs(v, u);
}
//cout << "debug\n";
out[u] = idx;
}
struct node {
int l, r, lazy, sum;
};
struct segment_tree {
node t[N << 2];
void push_up(int root) {
int ch = root << 1;
push_down(ch);
push_down(ch + 1);
t[root].sum = t[ch].sum + t[ch + 1].sum;
}
void push_down(int root) {
if(t[root].lazy != 0) {
// cal_lazy
t[root].sum = (t[root].r - t[root].l + 1) - t[root].sum;
// union_lazy
if(t[root].l != t[root].r) {
int ch = root << 1;
t[ch].lazy ^= t[root].lazy;
t[ch + 1].lazy ^= t[root].lazy;
}
// init_lazy
t[root].lazy = 0;
}
}
void build(int root, int l, int r) {
t[root].l = l;
t[root].r = r;
if(l != r) {
int ch = root << 1;
int mid = l + r >> 1;
build(ch, l, mid);
build(ch + 1, mid + 1, r);
} else {
t[root].lazy = t[root].sum = 0;
}
}
void update(int root, int l, int r) {
push_down(root);
if(t[root].l == l && t[root].r == r) {
//cout << "root" << root << "\n";
t[root].lazy ^= 1;
return;
}
int ch = root << 1;
int mid = t[root].l + t[root].r >> 1;
if(r <= mid) update(ch, l, r);
else if(l > mid) update(ch + 1, l, r);
else update(ch, l, mid), update(ch + 1, mid + 1, r);
push_up(root);
}
int query(int root, int l, int r) {
push_down(root);
if(t[root].l >= l && t[root].r <= r) {
return t[root].sum;
}
int ch = root << 1;
int mid = t[root].l + t[root].r >> 1;
if(r <= mid) return query(ch, l, r);
else if(l > mid) return query(ch + 1, l, r);
else return query(ch, l, mid) + query(ch + 1, mid + 1, r);
}
} st;
signed main() {
ios::sync_with_stdio(false), cin.tie(0);
int x;
cin >> n;
for(int i = 2; i <= n; ++i) {
cin >> x;
g[i].push_back(x), g[x].push_back(i);
}
dfs(1, -1);
st.build(1, 1, n);
//cout << "finsh\n";
for(int i = 1; i <= n; ++i) {
cin >> x;
if(x) st.update(1, in[i], in[i]);
//cout << "finshdd\n";
}
cin >> m;
string op;
while(m--) {
cin >> op >> x;
if(op == "get") {
cout << st.query(1, in[x], out[x]) << "\n";
} else {
st.update(1, in[x], out[x]);
}
}
return 0;
}