Codeforces Round #442 (Div. 2) 877E - Danil and a Part-time Job
emmmm第一次见的东西感觉都好神奇
这里dfs序可以通过对树的遍历对各个节点进行区间分配,那么在接下来的线段树中,可以转变为对每个节点所对应的子树进行访问
一开始感觉有些混乱,emmmm,理解上有困难的话……emmm,其实线段树维护的是区间,
而dfs序只是根据题意对节点(线段树的叶子?不要去管它的父亲或者线段树数组内部的结构)管辖区间的建立,因为题目中要求访问以*为根的子树的情况,在用到线段树时,
需要提供区间的左右端点,也就是dfs序所建立的L[*],R[*],只需要将主函数中访问线段树时的区间[L,R]换为【L[*],R[*]】就可以了……
emmmm好像说了一堆废话orz
#include<iostream> #include<stdio.h> #include<string> #include<vector> using namespace std; const int N = 2e5 + 5; vector<int>g[N]; int L[N], R[N]; int cnt=0, n, T; struct tree { int l, r, add, c[2]; }t[N << 2]; void init() { for (int i = 0; i < N; i++) g[i].clear(); cnt = 0; } void dfs(int u, int fa) { L[u] = ++cnt; for (auto v : g[u]) { if (v != fa) dfs(v, u); } R[u] = cnt; } void push_up(int rt) { for (int i = 0; i < 2; i++) t[rt].c[i] = t[rt << 1].c[i] + t[rt << 1 | 1].c[i]; } void push_down(int rt) { if (t[rt].add) { swap(t[rt << 1].c[0], t[rt << 1].c[1]); swap(t[rt << 1 | 1].c[0], t[rt << 1 | 1].c[1]); t[rt << 1].add ^= 1; t[rt << 1 | 1].add ^= 1; t[rt].add = 0; } } void build(int l, int r, int rt) { t[rt].l = l; t[rt].r = r; t[rt].add = 0; if (l == r) { t[rt].c[0] = 1; t[rt].c[1] = 0; return; } int mid = (l + r) >> 1; build(l, mid, rt << 1); build(mid + 1, r, rt << 1 | 1); push_up(rt); } void update(int l, int r, int rt) { if (t[rt].l == l&&t[rt].r == r) { t[rt].add ^= 1; swap(t[rt].c[0], t[rt].c[1]); return; } int mid = (t[rt].l + t[rt].r) >> 1; push_down(rt); if (r <= mid) update(l, r, rt << 1); else if (l > mid) update(l, r, rt << 1 | 1); else update(l, mid, rt << 1),update(mid+1, r, rt << 1 | 1); push_up(rt); } int query(int l, int r, int rt) { if (t[rt].r == r&&t[rt].l == l) return t[rt].c[1]; int mid = (t[rt].l + t[rt].r) >> 1; push_down(rt); if (r <= mid) return query(l, r, rt << 1); else if (l > mid) return query(l, r, rt << 1 | 1); else return query(l, mid, rt << 1) + query(mid+1,r, rt << 1 | 1); } int main() { init(); cin >> n; for (int i = 2; i <= n; i++) { cin >> T; g[T].push_back(i); } dfs(1, 1); build(1, cnt, 1); for (int i = 1; i <= n; i++) { int m; cin >> m; if (m) update(L[i], L[i], 1); } cin >> T; string s; for (int i = 0; i < T; i++) { int m; cin >> s >> m; if (s[0] == 'g') cout << query(L[m], R[m], 1) << endl; else update(L[m], R[m], 1); } return 0; }