链接
http://poj.org/problem?id=3321
大意
在一棵多叉树上有 n n 个节点,起初每个节点上都有一个苹果,中间会有两种操作:
- 询问以为根的子树共有几个苹果
- 改变 x x <script type="math/tex" id="MathJax-Element-117">x</script>号节点上的苹果,其苹果树取反(即0为1,1为0)
思路
其实这题我是想用线段树的。。。
树状数组+邻接表dfs遍历
就是利用dfs化树为链,然后就是基本的树状数组啦代码
#include<cstdio> #include<cstring> #define maxn 100001 #define make(a,b) memset(a,b,sizeof(a))//其实这并没有什么卵用 #define lb i&-i//lowbit using namespace std;int tot,n,x,y,m,q;char ch; struct node { int to,next; }edge[2*maxn]; int l[maxn],c[maxn],begin[maxn],end[maxn];//一堆数组 bool apple[maxn]; void add(int u,int v)//建图 { edge[++tot].to=v; edge[tot].next=l[u]; l[u]=tot; } void dfs(int k)//遍历 { begin[k]=m; for(int i=l[k];i;i=edge[i].next) dfs(edge[i].to); end[k]=++m; } void upd(int i,int d){for(;i<=n;i+=lb) c[i]+=d;return;}//更改 int sum(int i){int t=0;for(;i>0;i-=lb) t+=c[i];return t;}//求和 int main() { scanf("%d",&n); for(int i=1;i<n;i++) scanf("%d%d",&x,&y),add(x,y);//建图 dfs(1);//遍历 for(int i=1;i<=n;i++) upd(i,1);//初始化每棵树上都有苹果 scanf("%d",&q); while(q--) { while((ch=getchar())!='C'&&ch!='Q');scanf("%d",&x);//输入 if(ch=='C') { apple[x]^=1; if(apple[x]) upd(end[x],-1);//减掉 else upd(end[x],1);//加回 } else printf("%d\n",sum(end[x])-sum(begin[x]));//计算 } }