卡卡屋前有一株蘋果樹,每一年秋天,樹上長了許多蘋果。卡卡很喜歡蘋果。樹上有N個節點,卡卡給他們編號1到N,根的編號永遠是1.每一個節點上最多結一個蘋果。卡卡想要了解某一個子樹上一共結了多少蘋果。markdown
如今的問題是不斷會有新的蘋果長出來,卡卡也隨時可能摘掉一個蘋果吃掉。你能幫助卡卡嗎?app
邊表存儲樹
DFS時間戳
線段樹 ui
首先利用邊表將樹存儲下來,而後DFS打上時間戳。打上時間戳以後,咱們就知道書上節點對應維護線段樹的哪一段區間了。換句話說,每當題目給出一個點,要求更新的時候,咱們根據時間戳,肯定其點在線段樹上的位置。當題目給出一個區間,要求咱們查詢的時候,再根據時間戳,肯定線段樹區間左右端點。如此一來,就能夠將樹上信息,轉換到線段樹上來維護。spa
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define nmax 100010
using namespace std;
struct edge{
int to,next;
}edg[nmax<<1];
struct Tree{
int l,r,val;
int mid(){
return (l+r)>>1;
}
};
Tree tree[nmax<<2];
int head[nmax],in[nmax],out[nmax];
int tot = 0,n,m,time = 0;
void add(int u, int v){
edg[tot].to = v;
edg[tot].next = head[u];
head[u] = tot++;
}
void init(){
memset(head,-1,sizeof head);
memset(edg, 0, sizeof edg);
memset(tree,0,sizeof tree);
memset(in,0,sizeof in);
memset(out ,0, sizeof out);
tot= 0;
time = 0;
}
void dfs(int rt,int f){
time++;
in[rt] = time;
for(int i = head[rt]; i!= -1;i= edg[i].next){
int net = edg[i].to;
if(net != f) dfs(net,rt);
}
out[rt] = time;
}
void PushUp(int rt)
{
tree[rt].val = tree[rt<<1].val + tree[rt<<1|1].val;
}
void Build(int l, int r, int rt)
{
tree[rt].l = l; tree[rt].r = r;
if(l == r){
tree[rt].val = 1;
return;
}
Build(l,tree[rt].mid(),rt<<1);
Build(tree[rt].mid()+1,r,rt<<1|1);
PushUp(rt);
}
void UpdatePoint(int pos, int rt)
{
if(tree[rt].l == tree[rt].r){
tree[rt].val ^= 1;
return;
}
if(pos<= tree[rt].mid()) UpdatePoint(pos,rt<<1);
else UpdatePoint(pos,rt<<1|1);
PushUp(rt);
}
int Query(int l,int r,int rt)
{
if(l>tree[rt].r || r<tree[rt].l) return 0;
if(l <= tree[rt].l && tree[rt].r <= r) return tree[rt].val;
return Query(l,r,rt<<1) + Query(l,r,rt<<1|1);
}
int main()
{
while(scanf("%d",&n) != EOF){
init();
int u,v;
for(int i = 0;i<n-1;++i){
scanf("%d %d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1,0);
Build(1,n,1);
int m;scanf("%d",&m);
char op;int x;
for(int i = 0;i<m;++i){
scanf(" %c %d",&op,&x);
if(op == 'Q'){
printf("%d\n",Query(in[x],out[x],1));
}else{
UpdatePoint(in[x],1);
}
}
}
return 0;
}