Apple Tree(树状数组)

描述

 

Happy Christmas! Kaka likes apple very much, Santa Claus presents an apple tree for kaka. In this evening, a lot of apples will grow in the tree.

The tree has N forks which are connected by branches. Kaka numbers the forks by 1 to N and the root is always numbered by 1. Apples will grow on the forks and two apple won't grow on the same fork. kaka wants to know how many apples are there in a sub-tree, for his study of the produce ability of the apple tree.

The trouble is that a new apple may grow on an empty fork some time and kaka may pick an apple from the tree for his dessert. Can you help kaka?

输入

 

The first line contains an integer N (N ≤ 100,000) , which is the number of the forks in the tree.
The following N - 1 lines each contain two integers u and v, which means fork u and fork v are connected by a branch.
The next line contains an integer M (M ≤ 100,000).
The following M lines each contain a message which is either
"x" which means the existence of the apple on fork x has been changed. i.e. if there is an apple on the fork, then Kaka pick it; otherwise a new apple has grown on the empty fork.
or
"x" which means an inquiry for the number of apples in the sub-tree above the fork x, including the apple (if exists) on the fork x
Note the tree is full of apples at the beginning

输出

For every inquiry, output the correspond answer per line.

样例输入

 3

1 2

1 3
3
Q 1
C 2
Q 1

样例输出

3
2

题目大意是有一颗苹果树,以1这个节点为根节点 ,节点连接的话数据都是合理的,不会存在1在后面,必定是后一个节点连接前一个,C操作是改变某节点苹果状态,从无到有,从有到无,Q操作是查询该节点包括当前节点与其分支上苹果的数量总和

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstdio>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 const int MAX=100005;
 8 struct Tree
 9 {
10     int left,right,data;//left为左区间(本身),right为右区间(边界),表示该点的管理范围在[left,right],data显示有无苹果,1有,0无
11 }tree[MAX];
12 int n,m,side=1;
13 vector<int> vec[MAX];
14 int cnt[MAX];//在管理范围内的苹果数
15 
16 void DFS(int num)//为每个节点标记管理范围
17 {
18     tree[num].left=side;
19     int len=vec[num].size();
20     for(int i=0;i<len;i++){
21         side++;
22         DFS(vec[num][i]);
23     }
24     tree[num].right=side;
25 }
26 
27 int lowbit(int i)//表示求数组下标二进制的非0最低位所表示的值(树状数组原理)
28 {
29     return i&-i;//或i-(i&(i-1))或(i ^ (i-1))
30 }
31 
32 void update(int i,int val)//更新苹果数
33 {
34     while(i<=n){
35         cnt[i]+=val;
36         i+=lowbit(i);
37     }
38 }
39 
40 int getsum(int i)//求范围内总和
41 {
42     int sum=0;
43     while(i>=1){
44         sum+=cnt[i];
45         i-=lowbit(i);
46     }
47     return sum;
48 }
49 
50 int main()
51 {
52     int x,y;
53     char c;
54     memset(cnt,0,sizeof(cnt));
55     scanf("%d",&n);
56     for(int i=1;i<n;i++){
57         scanf("%d %d",&x,&y);
58         vec[x].push_back(y);
59     }
60     DFS(1);//从1开始递归进行标记
61     for(int i=1;i<=n;i++){
62         tree[i].data=1;//初始时都有苹果
63         update(i,1);
64     }
65     scanf("%d",&m);
66     for(int i=1;i<=m;i++){
67         getchar();
68         scanf("%c %d",&c,&x);
69         if(c=='C'){
70             int val=(tree[x].data==1?-1:1);//有苹果时val=-1,摘下,否则val=1,重新生长
71             update(tree[x].left,val);
72             tree[x].data=1-tree[x].data;//与原状态相反
73         }
74         else{
75             printf("%d
",getsum(tree[x].right)-getsum(tree[x].left-1));//右边界-左边界的前一个=该区间内总数
76         }
77     }
78     return 0;
79 }
原文地址:https://www.cnblogs.com/ChangeG1824/p/9493469.html