題意:
一棵蘋果樹有N個分叉,編號1---N(根的編號爲1),每個分叉只能有一顆蘋果或者沒有蘋果。 現在有兩種操作:
1.某個分叉上的蘋果從有變無或者從無邊有。
2.需要統計以某個分叉爲根節點時,它的子樹上(包括該分叉)共有多少蘋果。
分析: 有兩種操作,基本就是使用數據結構維護的題目了。開始想了很久,不懂如何將分叉轉化爲一維線性的樹狀數組維護。 看了下discuss,有人說了時間戳三字。想了想,發現如果按照節點遍歷的順序可以製造出時間上的線性關係。 例如:
連接情況爲:1---->2 1--->3 3--->4 3--->5
以1爲根節點開始dfs,則遍歷到每個點的時間可以爲 1---->1 3--->2 4--->3 5---->4 2--->5
用兩個數組begin,end統計以節點i爲根時,遍歷的第一個點的時間,和遍歷最後一個點的時間
所以:begin[1] = 1 ; end[1] = 5; begin[2] = 5 ; end[2] = 5; begin[3] = 2; end[3] = 4;........................................................
改變節點i的狀態,時間戳小於i的會受影響;求和時,只需求(begin[i],end[i])的和了............................這樣就變成了單點更新,區間求和的問題了。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <climits>//形如INT_MAX一類的
#define MAX 100005
#define INF 0x7FFFFFFF
#define REP(i,s,t) for(int i=(s);i<=(t);++i)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
#define L(x) x<<1
#define R(x) x<<1|1
# define eps 1e-5
//#pragma comment(linker, "/STACK:36777216") ///傳說中的外掛
using namespace std;
int begin[MAX],end[MAX],cnt[MAX],vis[MAX];
int c[MAX];
int n,m,step;
char op;
struct node {
int s,e,next;
} ed[MAX];
int head[MAX],num;
void init() {
memset(head,-1,sizeof(head));
num = 0;
step = 1;
memset(c,0,sizeof(c));
memset(cnt,1,sizeof(cnt));
memset(vis,0,sizeof(vis));
}
void addedge(int s,int e) {
ed[num].s = s;
ed[num].e = e;
ed[num].next = head[s];
head[s] = num ++;
}
int lowbit(int x) {
return x & (-x);
}
void update(int x,int va) {
while(x > 0) {
c[x] += va;
x -= lowbit(x);
}
}
int query(int x) {
int sum = 0;
while(x <= n) {
sum += c[x];
x += lowbit(x);
}
return sum;
}
void dfs(int v0) {
vis[v0] = 1;
begin[v0] = step;
for(int i=head[v0]; i != -1; i = ed[i].next) {
int e = ed[i].e;
if(vis[e] == 0) {
step ++;
dfs(e);
}
}
end[v0] = step;
}
int main() {
init();
scanf("%d",&n);
int x,y;
for(int i=0; i<n-1; i++) {
scanf("%d%d",&x,&y);
addedge(x,y);
}
dfs(1);
for(int i=1; i<=n; i++) update(i,1);
scanf("%d",&m);
for(int i=0; i<m; i++) {
getchar();
scanf("%c%d",&op,&x);
if(op == 'Q') {
printf("%d\n",query(begin[x]) - query(end[x] + 1));
}
if(op == 'C') {
cnt[x] ++;
if(cnt[x] % 2 == 0) update(begin[x],-1);
else update(begin[x],1);
}
}
return 0;
}