题目链接:http://poj.org/problem?id=3321
思路:将一个树映射成树状数组,用dfs 对图中的苹果树进行遍历
dfs遍历顺序i | 1 | 3 | 4 | 5 | 2 |
start[i] | 1 | 2 | 3 | 4 | 5 |
end[i] | 5 | 4 | 3 | 4 | 5 |
这样求1号树叉上的苹果总数就是求从1到5(start[1]=1,start[2]=3,start[3]=4,start[4]=5,start[5]=2)号树叉上的苹果数量,同理3号树叉上的苹果总数就是从2到4号(start[2]=3,start[3]=4,start[4]=5)树叉上的苹果数量
#include<cstdio>
using namespace std;
const int num=100005;
int c[num],n,m,st[num],ed[num],ord=0,head[num],e,vis[num],p[num];
//p记录i的树叉上是否有苹果,初始为有;ord记录遍历顺序,可理解为时间
struct node
{
int u,next;
}edge[num*2];//邻接表
void init()
{
int i;
for(i=0;i<=n;i++)
{
head[i]=-1;
c[i]=0;
vis[i]=0;
p[i]=1;
}
e=0;
}
void add(int a,int b)
{
edge[e].u=b;
edge[e].next=head[a];
head[a]=e++;
}
int lowbit (int a)
{
return a&(-a);
}
void updata(int a,int add)
{
while(a<=n)
{
c[a]+=add;
a+=lowbit(a);
}
}
int sum(int a)
{
int ans=0;
while(a>0)
{
ans+=c[a];
a-=lowbit(a);
}
return ans;
}
void dfs(int a)
{
int i;
ord++;
st[a]=ord;
vis[a]=1;
for(i=head[a];i!=-1;i=edge[i].next)
{
if(vis[edge[i].u]==0)
dfs(edge[i].u);
}
ed[a]=ord;
}
int main()
{
int i,a,b;
char s[3];
//freopen("in.txt","r",stdin);
scanf("%d",&n);
init();
for(i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
for(i=1;i<=n;i++)
updata(i,1);
dfs(1);
scanf("%d",&m);
while(m--)
{
scanf("%s",s);
if(s[0]=='C'&&s[1]=='\0')
{
scanf("%d",&a);
if(p[a]==1)
{
updata(st[a],-1);
p[a]=0;
}
else
{
updata(st[a],1);
p[a]=1;
}
}
else if(s[0]=='Q'&&s[1]=='\0')
{
scanf("%d",&a);
printf("%d\n",sum(ed[a])-sum(st[a]-1));
}
}
return 0;
}