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

【POJ 3321】Apple Tree

2016-07-26 01:32 393 查看
有n个节点以1为根节点的树,给你树的边关系u-v,一开始每个节点都有一个苹果,接下来有两种操作,C x改变节点x的苹果状态,Q x查询x为根的树的所有苹果个数。

求出树的dfs序,st[i]保存i的进入时间戳,ed[i]保存i的退出时间戳,则st[i]到ed[i]就是子树节点的对应时间戳。
每个节点打了两次时间戳,其中ed[i]会等于最后访问的一个子节点的st[i]。
于是用线段树/树状数组的单点修改和区间求和就可以解决。

#include<cstdio>
#define N 100005
using namespace std;
int n,m,id,cnt;
int q
,st
,ed
,head
;
int rl[N<<2],rr[N<<2],sum[N<<2];
struct edge{
int to,next;
}e[N<<1];
void add(int u,int v){
e[++cnt]=(edge){v,head[u]};
head[u]=cnt;
}
void dfs(int x,int fa){
st[x]=++id;
for(int i=head[x];i;i=e[i].next)
if(e[i].to!=fa)
dfs(e[i].to,x);
ed[x]=id;
}
void build(int k,int l,int r){
rl[k]=l;rr[k]=r;
if(l==r){
sum[k]=1;
return;
}
int mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
sum[k]=sum[k<<1]+sum[k<<1|1];
}
int query(int k,int a,int b){
int l=rl[k],r=rr[k];
if(a<=l&&r<=b) return sum[k];
if(b<l||a>r)return 0;
return query(k<<1,a,b)+query(k<<1|1,a,b);
}
void modify(int k,int x){
int l=rl[k],r=rr[k],mid=(l+r)>>1;
if(l==r){
sum[k]^=1;
return;
}
if(x<=mid)modify(k<<1,x);
else modify(k<<1|1,x);
sum[k]=sum[k<<1]+sum[k<<1|1];
}
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1,0);
scanf("%d",&m);
build(1,1,n);
for(int i=1;i<=m;i++){
char op;
scanf(" %c",&op);
int x;
scanf("%d",&x);
if(op=='Q')
printf("%d\n",query(1,st[x],ed[x]));
else
modify(1,st[x]);
}
return 0;
}


树状数组

#include<cstdio>
#define N 100005
using namespace std;
int n,m,id,cnt;
int q
,st
,ed
,head
;
int cal
,a
;
struct edge{
int to,next;
}e[N<<1];
void add(int u,int v){
e[++cnt]=(edge){v,head[u]};
head[u]=cnt;
}
void dfs(int x,int fa){
st[x]=++id;
for(int i=head[x];i;i=e[i].next)
if(e[i].to!=fa)
dfs(e[i].to,x);
ed[x]=id;
}
int getsum(int x){
int s=0;
for(;x;x-=x&(-x))s+=cal[x];
return s;
}
void update(int v,int x){
for(;x<=n;x+=x&(-x))cal[x]+=v;
}
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
dfs(1,0);
scanf("%d",&m);
for(int i=1;i<=n;i++)update(1,i);
for(int i=1;i<=m;i++){
char op;
scanf(" %c",&op);
int x;
scanf("%d",&x);
if(op=='C'){
update(a[x]?1:-1,st[x]);
a[x]^=1;
}
else
printf("%d\n",getsum(ed[x])-getsum(st[x]-1));
}
return 0;
}


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