六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 29|回复: 0

poj3321——Apple Tree//树状数组

[复制链接]

升级  93.8%

309

主题

309

主题

309

主题

进士

Rank: 4

积分
969
 楼主| 发表于 2013-1-26 13:38:11 | 显示全部楼层 |阅读模式
记住树状数组的基本操作: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[n]增加m,可以通过调用如下函数实现void add(int i,int v){   while (i<=n)   {      a[i]+=v;      i+=lowbit(i);   }}如果要统计a[1]到a[n]之间的和,可以通过调用如下函数实现int sum(int i){   int s=0;   while (i>0)   {      s+=a[i];      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[maxn];int head[maxn],cnt,c[maxn*2];bool have[maxn];class tree{public:int st,ed;};tree st[maxn];void dfs(int v){st[v].st =++cnt;int i;for(i=head[v];i;i=g[i].next ){dfs(g[i].v );}st[v].ed =++cnt;}int lowbit(int x){return x&(-x);}void add(int t,int v){while(t<maxn){c[t]+=v;t+=lowbit(t);}}int getsum(int t){int s=0;while(t>0){s+=c[t];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[cnt].next =head[a];head[a]=cnt;}cnt=0;dfs(1);memset(have,true,sizeof(have));for(i=1;i<=n;i++){add(st[i].st,1);add(st[i].ed,1);}scanf("%d",&m);getchar();while(m--){scanf("%c %d",&ch,&a);getchar();if(ch=='Q'){lsum=getsum(st[a].st-1 );rsum=getsum(st[a].ed );printf("%d\n",(rsum-lsum)/2);}else if(ch=='C'){if(have[a]){have[a]=false;add(st[a].st ,-1);add(st[a].ed ,-1);}else {have[a]=true;add(st[a].st ,1);add(st[a].ed ,1);}}}return 0;}
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表