题目大意:有一颗长满苹果的苹果树,有两个操作。
1.询问以一个点为根的子树中有多少个苹果。
2.看看一个点有没有苹果,假设没有苹果。那么那里就立即长出一个苹果(= =!);否则就把那个苹果摘下来。
思路:进行一次深搜,将每一个节点最開始出现的时间和最后出现的时间记在一个数组里,那么这两点之间的点就是它以及它的子树的二倍,然后就用树状数组来维护区间和即可了。
CODE:
#include#include #include #include #define MAX 200010using namespace std;pair pos[MAX];int points,asks;int head[MAX],total;int next[MAX << 1],aim[MAX << 1];int cnt;bool src[MAX];int fenwick[MAX];char c[10];inline void Add(int x,int y);void DFS(int x,int last);inline void Fix(int x,int c);inline int GetSum(int x);int main(){ cin >> points; for(int x,y,i = 1;i < points; ++i) { scanf("%d%d",&x,&y); Add(x,y),Add(y,x); } DFS(1,-1); memset(src,true,sizeof(src)); for(int i = 1;i <= points; ++i) Fix(pos[i].first,1),Fix(pos[i].second,1); cin >> asks; for(int x,i = 1;i <= asks; ++i) { scanf("%s%d",c,&x); if(c[0] == 'Q') printf("%d\n",(GetSum(pos[x].second) - GetSum(pos[x].first - 1)) >> 1); else { if(src[x]) { Fix(pos[x].first,-1); Fix(pos[x].second,-1); src[x] = false; } else { Fix(pos[x].first,1); Fix(pos[x].second,1); src[x] = true; } } } return 0;}inline void Add(int x,int y){ next[++total] = head[x]; aim[total] = y; head[x] = total;}void DFS(int x,int last){ pos[x].first = ++cnt; for(int i = head[x];i;i = next[i]) { if(aim[i] == last) continue; DFS(aim[i],x); } pos[x].second = ++cnt;}inline void Fix(int x,int c){ for(;x <= (points << 1);x += x&-x) fenwick[x] += c;}inline int GetSum(int x){ int re = 0; for(;x;x -= x&-x) re += fenwick[x]; return re;}