Description
Given a rooted tree, each node has a boolean (0 or 1) labeled on it. Initially, all the labels are 0.
We define this kind of operation: given a subtree, negate all its labels.
And we want to query the numbers of 1's of a subtree.
Input
Multiple test cases.
First line, two integer N and M, denoting the numbers of nodes and numbers of operations and queries.(1<=N<=100000, 1<=M<=10000)
Then a line with N-1 integers, denoting the parent of node 2..N. Root is node 1.
Then M lines, each line are in the format "o node" or "q node", denoting we want to operate or query on the subtree with root of a certain node.
Output
For each query, output an integer in a line.
Output a blank line after each test case.
题目大意:给一棵多叉树,初始值都为0,o x为翻转以x为根的子树,q x为查询以x为根的子树有多少个1
思路:这数据范围,暴力是不行的,怎么暴力都是不行的>_<。这题的要求是:修改一大片、查询一大片,比较容易想到的就是线段树(树状数组也可以,不过要翻转嘛……好像有难度……反正我不会>_<)。问题是这玩意儿怎么转换成线段树呢?要转化成线段树,就要把每个点的子孙们都放到一片连续的空间里。这时,若使用DFS,遍历的顺序刚刚好符合要求,于是我们就DFSo(∩_∩)o 。DFS途中就可以算出每个点的及其子孙覆盖的区域。然后变成线段树之后呢,随便搞搞就行了o(∩_∩)o
1 #include <cstdio> 2 #include <cstring> 3 4 const int MAX = 100010; 5 6 int flip[MAX*4], sum[MAX*4], cnt[MAX*4];//tree 7 int head[MAX], next[MAX], to[MAX], ecnt; 8 int beg[MAX], size[MAX], dfs_clock; 9 int y1, y2; 10 11 void tle() {while(1) ;} 12 13 void init() { 14 ecnt = 1; 15 dfs_clock = 0; 16 memset(head, 0, sizeof(head)); 17 memset(flip, 0, sizeof(flip)); 18 memset(cnt, 0, sizeof(cnt)); 19 } 20 21 void add_edge(int u, int v) { 22 to[ecnt] = v; next[ecnt] = head[u]; head[u] = ecnt++; 23 } 24 25 void dfs(int x) { 26 size[x] = 1; 27 beg[x] = ++dfs_clock; 28 for(int p = head[x]; p; p = next[p]) { 29 dfs(to[p]); 30 size[x] += size[to[p]]; 31 } 32 } 33 34 void maintain(int x, int l, int r) { 35 int lc = x * 2, rc = x * 2 + 1; 36 if(l < r) { 37 cnt[x] = cnt[rc] + cnt[lc]; 38 } 39 } 40 41 void pushdown(int x) { 42 int lc = x * 2, rc = x * 2 + 1; 43 if(flip[x]) { 44 flip[x] = 0; 45 flip[lc] ^= 1; 46 cnt[lc] = sum[lc] - cnt[lc]; 47 flip[rc] ^= 1; 48 cnt[rc] = sum[rc] - cnt[rc]; 49 } 50 } 51 52 void update(int x, int l, int r) { 53 int lc = x * 2, rc = x * 2 + 1; 54 if(y1 <= l && r <= y2) { 55 flip[x] ^= 1; 56 cnt[x] = sum[x] - cnt[x]; 57 } 58 else { 59 pushdown(x); 60 int mid = (l + r) / 2; 61 if(y1 <= mid) update(lc, l, mid); 62 if(mid < y2) update(rc, mid + 1, r); 63 maintain(x, l, r); 64 } 65 } 66 67 int ans; 68 69 void query(int x, int l, int r) { 70 int lc = x * 2, rc = x * 2 + 1; 71 if(y1 <= l && r <= y2) ans += cnt[x]; 72 else { 73 pushdown(x); 74 int mid = (l + r) / 2; 75 if(y1 <= mid) query(lc, l, mid); 76 if(mid < y2) query(rc, mid + 1, r); 77 } 78 } 79 80 void build(int x, int l, int r) { 81 int lc = x * 2, rc = x * 2 + 1; 82 if(l == r) { 83 sum[x] = 1; 84 } 85 else { 86 int mid = (l + r) / 2; 87 build(lc, l, mid); 88 build(rc, mid + 1, r); 89 sum[x] = sum[lc] + sum[rc]; 90 } 91 } 92 93 int main() { 94 int n, m, x; 95 char c[2]; 96 while(scanf("%d%d", &n, &m) != EOF) { 97 init(); 98 for(int i = 2; i <= n; ++i) { 99 scanf("%d", &x); 100 add_edge(x, i); 101 } 102 dfs(1); 103 build(1, 1, n); 104 while(m--) { 105 scanf("%s%d", c, &x); 106 y1 = beg[x]; y2 = beg[x] + size[x] - 1; 107 if(c[0] == 'o') { 108 update(1, 1, n); 109 } 110 if(c[0] == 'q') { 111 ans = 0; 112 query(1, 1, n); 113 printf("%d\n", ans); 114 } 115 } 116 puts(""); 117 } 118 }