Original question: zoj 3686 http://acm.zju.edu.cn/onlinejudge/showProblem.do? Problemcode = 3686.
This question was originally a relatively watery line segment tree. As a result, I had a mark for several hours .. Ah. Too weak.
First, the DFS tree is transformed from a tree structure to a linear structure. Each node has a first Traversal Time and the last Traversal Time. The timestamp between them is the time stamp of the subtree, you can use the line segment tree to update the interval to achieve the effect of updating the subtree. Lazy operations are used to save time.
Pitfall: During update, it cannot be written as tree [RT]. mark = 1, instead of tree [RT]. mark ^ = 1; because if an even number of times of continuous update is equivalent to nothing, but each update is indeed updated, tree [RT] will be used for every Pushdown operation. the mark is 0, that is, tree [RT]. mark cannot be maintained, so what I don't understand is why we want to be different or 1, rather than directly equal to 1. I need to ask the gods for advice, if you see and know, kindly advise me.
Code:
# Include <iostream> # include <cstdio> # include <cstring> # include <cmath> # include <algorithm> # include <vector> using namespace STD; # define n 100007 struct node {int L, R;} p [N]; struct tree {int sum, mark;} tree [8 * n]; int time; vector <int> G [N]; void pushup (int rt) {tree [RT]. sum = tree [2 * RT]. sum + tree [2 * RT + 1]. SUM;} void build (int l, int R, int RT) {tree [RT]. sum = tree [RT]. mark = 0; If (L = r) return; int mid = (L + R)/2; build (L, mid, 2 * RT); Build (Mid + 1, R, 2 * RT + 1); pushup (RT );} void Pushdown (int l, int R, int RT) {If (! Tree [RT]. mark) return; int mid = (L + r)/2; tree [2 * RT]. mark ^ = 1; // not "tree [2 * RT]. mark = tree [RT]. mark "tree [2 * RT + 1]. mark ^ = 1; tree [2 * RT]. sum = (mid-L + 1)-tree [2 * RT]. SUM; tree [2 * RT + 1]. sum = (R-mid)-tree [2 * RT + 1]. SUM; tree [RT]. mark = 0;} void Update (int l, int R, int AA, int BB, int RT) {If (AA <= L & BB> = r) {tree [RT]. mark ^ = 1; // not "tree [RT]. mark = 1 ", because even number operations offset each other tree [RT]. sum = r-L + 1-tree [RT]. SUM; retu Rn;} Pushdown (L, R, RT); int mid = (L + r)/2; If (AA <= mid) Update (L, mid, AA, BB, 2 * RT); If (BB> mid) Update (Mid + 1, R, AA, BB, 2 * RT + 1); pushup (RT );} void DFS (int u) {P [u]. L = Time ++; For (INT I = 0; I <G [u]. size (); I ++) DFS (G [u] [I]); P [u]. R = Time ++;} int query (int l, int R, int AA, int BB, int RT) {If (AA> r | BB <L) return 0; if (AA <= L & BB> = r) return tree [RT]. SUM; Pushdown (L, R, RT); int mid = (L + r)/2; return query (L, mi D, AA, BB, 2 * RT) + query (Mid + 1, R, AA, BB, 2 * RT + 1);} int main () {int N, m, I, j, X; char ss [3]; while (scanf ("% d", & N, & M )! = EOF) {for (I = 0; I <= N; I ++) g [I]. clear (); for (I = 2; I <= N; I ++) {scanf ("% d", & X); G [X]. push_back (I);} time = 1; DFS (1); Build (1, 2 * n, 1); While (M --) {scanf ("% S % d ", SS, & X); If (ss [0] = 'O') Update (1, 2 * n, p [X]. l, P [X]. r, 1); else printf ("% d \ n", query (1, 2 * n, p [X]. l, P [X]. r, 1)/2);} puts ("");} return 0 ;}View code