您的位置:首页 > 移动开发

POJ 3321 Apple Tree (树状数组)

2012-08-17 20:24 155 查看
http://poj.org/problem?id=3321

题意:给出一颗苹果树,开始每个树叉上都有 一个苹果,苹果树总是以1为根,Q 1表示1树枝上有多少苹果,C 2表示更新树枝2上的苹果,以前有苹果变成没有,以前没有变成有,树杈上的苹果数不超过1

分析:插入,删除频繁,还需要算和,10^5的数据量,用线段树或树状数组,但是给出的是一棵树,不在一条线上。。。有时候不能看出什么是区间,就要仔细观察,造出“区间”,

如果从1根节点出发,dfs遍历树一遍,那遍历每个节点的时间是一条线,把时间划成区间。。。每个节点有两个时间戳,low[]表示开始时间,high[]表示结束时间。那么这个树枝上苹果的个数就是开始时间和结束时间之间的苹果

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#define nMAX 100005
using namespace std;
int low[nMAX],high[nMAX],c[nMAX],head[nMAX];
int n,m,s_edge,times;
bool vs[nMAX],has[nMAX];
struct Edge
{
int u,v,nxt;
}edge[nMAX*2];
struct Tree
{
int l,r;
}tree[nMAX*3+100];
void addedge(int u,int v)
{
s_edge++;
edge[s_edge].v=v;
edge[s_edge].nxt=head[u];
head[u]=s_edge;
}
void dfs(int u)
{
low[u]=++times;
vs[u]=1;
for(int e=head[u];e;e=edge[e].nxt)
{
int v=edge[e].v;
if(!vs[v]) dfs(v);
}
high[u]=times;
}

int lowbit(int x)
{
return x&(-x);
}
void add(int i ,int num)
{
while(i<=n)
{
c[i]+=num;
i+=lowbit(i);

}
}
int sum(int i)
{
int ans=0;
while(i>=1)
{
ans+=c[i];
i-=lowbit(i);
}
return ans;

}
int main()
{
char ch;
int i,j,k;
while(~scanf("%d",&n))
{
memset(head,0,sizeof(head));
s_edge=0;
for(k=1;k<n;k++)
{
scanf("%d%d",&i,&j);
addedge(i,j);
addedge(j,i);
}
memset(c,0,sizeof(c));
for(i=1;i<=n;i++)//每个树枝都有apple
add(i,1);
times=0;
memset(vs,0,sizeof(vs));
dfs(1);
memset(has,0,sizeof(has));//都有
scanf("%d",&m);
while(m--)
{
getchar();
scanf("%c%d",&ch,&i);
if(ch=='Q')
{
int ans=sum(high[i])-sum(low[i]-1);
printf("%d\n",ans);
}
else
{
if(!has[i]){add(low[i],-1);has[i]=1;}
else {add(low[i],1);has[i]=0;}

}
}
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: