好想去骑车。
题意
一棵树,非二叉,点个数达到五次方,每个点可能有一个苹果或没有,初始都有,进行Q次操作
询问:问一棵子树上有多少苹果
修改:修改一个点上有无苹果的状态
IO
Input
The first line contains an integer N (N ≤ 100,000) , which is the number of the forks in the tree.
The following N – 1 lines each contain two integers u and v, which means fork u and fork v are connected by a branch.
The next line contains an integer M (M ≤ 100,000).
The following M lines each contain a message which is either
“C x” which means the existence of the apple on fork x has been changed. i.e. if there is an apple on the fork, then Kaka pick it; otherwise a new apple has grown on the empty fork.
or
“Q x” which means an inquiry for the number of apples in the sub-tree above the fork x, including the apple (if exists) on the fork x
Note the tree is full of apples at the beginning
Output
For every inquiry, output the correspond answer per line.
分析
用dfs先序遍历,对树上的点重新编号,并记录两种编号对应关系。
之所以好久没想出来怎么破,就是没想到先序遍历的性质:子树上根节点的编号总是最小,且子树上所有点的编号是连续的一段。
在这样的性质下,就可以在dfs时确定每个子树的编号连续段,也就是从子树根节点编号到一个最大值。所以每次查询一棵子树的苹果数量就变成了查询数组区间和,用树状数组和线段树都可。修改信息是单点修改,都很水。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define MXN 210000
int n,m;
int first[MXN],nxt[MXN],vv[MXN],count;
int idx[MXN],cnt;
int high[MXN];
int a[MXN],c[MXN];
bool flag[MXN];
int lowbit[MXN];
void init(){
cnt=1;
count=0;
memset(flag,false,sizeof(flag));
memset(first,-1,sizeof(first));
memset(c,0,sizeof(c));
for(int i=1;i<=n;++i){
a[i]=1;
for(int j=i;j<=n;j+=lowbit[j])
c[j]+=1;
}
}
void add(int u,int v){
nxt[count]=first[u];
first[u]=count;
vv[count]=v;
++count;
}
void dfs(int now){
flag[now]=true;
idx[now]=cnt++;
for(int i=first[now];i!=-1;i=nxt[i]) if(!flag[vv[i]])
dfs(vv[i]);
high[idx[now]]=cnt-1;
}
void update(int loc){
int tem=1;
if(a[loc]) tem=-1;
a[loc]+=tem;
for(int i=loc;i<=n;i+=lowbit[i])
c[i]+=tem;
}
int find(int loc){
int ret=0;
for(int i=loc;i>0;i-=lowbit[i])
ret+=c[i];
return ret;
}
int main(){
for(int i=0;i<MXN;++i) lowbit[i]=i&(-i);
while(scanf("%d",&n)!=EOF){
init();
for(int i=1;i<n;++i){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1);
scanf("%d",&m);
for(int Q=0;Q<m;++Q){
char ins[2];
int tem;
scanf("%s%d",ins,&tem);
if(ins[0]=='Q')
printf("%d\n",find(high[idx[tem]])-find(idx[tem]-1));
else update(idx[tem]);
}
}
return 0;
}