[CodeForces877 E.Danil and a Part-time Job]dfs序+线段树
分类:Data Structure
SegMent Tree
dfn
1. 题目链接
[CodeForces877 E. Danil and a Part-time Job]
2. 题意描述
有一棵
n
个节点的树。树上每个节点有一个权值(0或者1)。有
数据范围:
(1 ≤ n,q ≤ 200,000)
3. 解题思路
水题。对一棵子树的操作或询问,可以转化为对dfs序的操作。
然后就是线段树的区间更新和区间询问操作。
4. 实现代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double lb;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> puu;
typedef pair<lb, lb> pbb;
typedef vector<int> vi;
const int inf = 0x3f3f3f3f;
const ll infl = 0x3f3f3f3f3f3f3f3fLL;
template<typename T> inline void umax(T &a, T b) { a = max(a, b); }
template<typename T> inline void umin(T &a, T b) { a = min(a, b); }
template<typename T> inline T randIntv(const T& a, const T& b) { return (T)rand() % (b - a + 1) + a; }
const int MAXN = 200005;
int n, q;
struct Edge {
int v, next;
} edge[MAXN];
int head[MAXN], tot, w[MAXN];
int dfn[MAXN][2], seq[MAXN << 1], idx;
void edge_init() {
idx = tot = 0;
memset(head, -1, sizeof(head));
}
void edge_ins(int u, int v) {
edge[tot] = Edge{v, head[u]};
head[u] = tot ++;
}
void dfs(int u) {
dfn[u][0] = ++ idx;
seq[idx] = u;
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].v;
dfs(v);
}
dfn[u][1] = ++ idx;
seq[idx] = u;
}
#define lch (rt << 1)
#define rch (rt << 1 | 1)
#define lson l, md, lch
#define rson md + 1, r, rch
int sum[MAXN << 3];
bool lazy[MAXN << 3];
inline void pushUp(const int& rt) { sum[rt] = sum[lch] + sum[rch]; }
inline void pushDw(const int& w, const int& rt) {
if (lazy[rt]) {
int wr = (w >> 1), wl = w - wr;
sum[lch] = wl - sum[lch];
sum[rch] = wr - sum[rch];
lazy[lch] ^= 1;
lazy[rch] ^= 1;
lazy[rt] = 0;
}
}
void build(int l, int r, int rt) {
lazy[rt] = false;
if (l == r) {
sum[rt] = w[seq[l]];
return;
}
int md = (l + r) >> 1;
build(lson);
build(rson);
pushUp(rt);
}
void update(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
lazy[rt] ^= 1;
sum[rt] = (r - l + 1) - sum[rt];
return;
}
pushDw(r - l + 1, rt);
int md = (l + r) >> 1;
if (L <= md) update(L, R, lson);
if (R > md) update(L, R, rson);
pushUp(rt);
}
int query(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) return sum[rt];
pushDw(r - l + 1, rt);
int md = (l + r) >> 1, ret = 0;
if (L <= md) ret += query(L, R, lson);
if (R > md) ret += query(L, R, rson);
return ret;
}
int main() {
#ifdef ___LOCAL_WONZY___
freopen ("input.txt", "r", stdin);
#endif // ___LOCAL_WONZY___
char op[10]; int v;
scanf("%d", &n);
edge_init();
for (int i = 2; i <= n; ++i) {
int fa; scanf("%d", &fa);
edge_ins(fa, i);
}
for (int i = 1; i <= n; ++i) scanf("%d", &w[i]);
dfs(1);
build(1, idx, 1);
scanf("%d", &q);
while (q --) {
scanf("%s %d", op, &v);
if (op[0] == 'g') {
int ans = query(dfn[v][0], dfn[v][1], 1, idx, 1);
ans >>= 1;
printf("%d\n", ans);
} else {
update(dfn[v][0], dfn[v][1], 1, idx, 1);
}
}
#ifdef ___LOCAL_WONZY___
cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif // ___LOCAL_WONZY___
return 0;
}