ZOJ 3686 A Simple Tree Problem(线段树)

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 }
View Code

 

你可能感兴趣的:(simple)