44424742 发表于 2013-1-26 13:38:11

poj3321——Apple Tree//树状数组

记住树状数组的基本操作:http://hi.baidu.com/wuxyy/blog/item/a4ad808b59be8bd2fd1f109d.html
http://writeblog.csdn.net/PostEdit.aspx?entryId=6376639
int lowbit(int x){   return x&(x^(x–1));}利用机器补码的特点,这个函数可以改得更方便int lowbit(int i){   return i&(-i);}如果要把a增加m,可以通过调用如下函数实现void add(int i,int v){   while (i<=n)   {      a+=v;      i+=lowbit(i);   }}如果要统计a到a之间的和,可以通过调用如下函数实现int sum(int i){   int s=0;   while (i>0)   {      s+=a;      i-=lowbit(i);   }   return s;}
此题思路:将每个点定一个时间戳。比如题目中给的树dfs()之后,点1为1,6,点2为2,3,点3为4,5.这样,查询1时,统计1--6之间的apple,再将结果除以2即可。
#include<iostream>#include<cstdio>#include<string>using namespace std;#define maxn 1000005int n,m;class map{public:int v,next;};map g;int head,cnt,c;bool have;class tree{public:int st,ed;};tree st;void dfs(int v){st.st =++cnt;int i;for(i=head;i;i=g.next ){dfs(g.v );}st.ed =++cnt;}int lowbit(int x){return x&(-x);}void add(int t,int v){while(t<maxn){c+=v;t+=lowbit(t);}}int getsum(int t){int s=0;while(t>0){s+=c;t-=lowbit(t);}return s;}int main(){int i,a,b,lsum,rsum;char ch;cnt=0;scanf("%d",&n);for(i=1;i<n;i++){scanf("%d%d",&a,&b);g[++cnt].v =b;g.next =head;head=cnt;}cnt=0;dfs(1);memset(have,true,sizeof(have));for(i=1;i<=n;i++){add(st.st,1);add(st.ed,1);}scanf("%d",&m);getchar();while(m--){scanf("%c %d",&ch,&a);getchar();if(ch=='Q'){lsum=getsum(st.st-1 );rsum=getsum(st.ed );printf("%d\n",(rsum-lsum)/2);}else if(ch=='C'){if(have){have=false;add(st.st ,-1);add(st.ed ,-1);}else {have=true;add(st.st ,1);add(st.ed ,1);}}}return 0;}
页: [1]
查看完整版本: poj3321——Apple Tree//树状数组