题意:
给你一个n个节点的树,每个节点上一开始都有一个苹果,现在有两种操作:
Q x :查询 x 节点以及它的子树上一共有多少苹果;
C x :若 x 节点上没有苹果,则增加一个,反之,则减少一个;
思路:
这是一个区间查询,单点修改的问题,我们就会想到用树状数组来做,但是怎么去维护树上的区间又是一个问题;
于是想到了用 dfs序 ,记录每一个节点的 left 和 right 也就转化成了区间问题;
1 /* 2 * @Author: windystreet 3 * @Date: 2018-08-02 22:10:44 4 * @Last Modified by: windystreet 5 * @Last Modified time: 2018-08-02 22:56:03 6 */ 7 #include<stdio.h> 8 #include<string.h> 9 #include<algorithm> 10 #include<vector> 11 12 using namespace std; 13 14 #define X first 15 #define Y second 16 #define eps 1e-2 17 #define gcd __gcd 18 #define pb push_back 19 #define PI acos(-1.0) 20 #define lowbit(x) (x)&(-x) 21 #define bug printf("!!!!!\n"); 22 #define mem(x,y) memset(x,y,sizeof(x)) 23 24 typedef long long LL; 25 typedef long double LD; 26 typedef pair<int,int> pii; 27 typedef unsigned long long uLL; 28 29 const int maxn = 1e5+7; 30 const LL INF = 1<<30; 31 const int mod = 1e9+7; 32 typedef vector<int> Ve; 33 vector<Ve>G(maxn); 34 int left[maxn],right[maxn],cnt=1,n; 35 int tree[maxn],vis[maxn]; 36 37 int query(int x){ 38 int res = 0; 39 while(x){ 40 res+=tree[x]; 41 x-=lowbit(x); 42 } 43 return res; 44 } 45 void add(int x,int v){ 46 for(int i=x;i<=n;i+=lowbit(i)){ 47 tree[i]+=v; 48 } 49 return ; 50 } 51 void dfs(int x){ 52 left[x] = cnt; // 记录左端点的id 53 int sz = G[x].size(); 54 for(int i=0;i<sz;i++){ 55 cnt++; 56 dfs(G[x][i]); 57 } 58 right[x]=cnt; // 记录右端点的id 59 } 60 61 void solve() 62 { 63 cnt = 1; 64 int x,y,m; 65 char op[3]; 66 for(int i=0;i<=n;i++){tree[i]=0;vis[i]=1;G[i].clear();} 67 for(int i=1;i<n;i++){ 68 scanf("%d%d",&x,&y); 69 G[x].pb(y); // 存图 70 } 71 dfs(1); // dfs序 72 for(int i=1;i<=n;i++){ 73 add(i,1); // 每个点一开始都有一个苹果 74 } 75 scanf("%d",&m); 76 for(int i=0;i<m;i++){ 77 scanf("%s%d",op,&x); 78 if(op[0]==‘Q‘){ // 区间查询 79 printf("%d\n",query(right[x])-query(left[x]-1)); 80 }else{ 81 if(vis[x])add(left[x],-1); // 单点修改 82 else add(left[x],1); 83 vis[x]=!vis[x]; // 取反 84 } 85 } 86 return ; 87 } 88 89 int main() 90 { 91 // freopen("in.txt","r",stdin); 92 // freopen("out.txt","w",stdout); 93 // ios::sync_with_stdio(false); 94 while(scanf("%d",&n)!=EOF){ 95 // printf("Case %d: ",cas++); 96 solve(); 97 } 98 return 0; 99 }