前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【POJ 3321】Apple Tree

【POJ 3321】Apple Tree

作者头像
饶文津
发布2020-06-02 15:43:27
5480
发布2020-06-02 15:43:27
举报
文章被收录于专栏:饶文津的专栏饶文津的专栏

有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]。

于是用线段树/树状数组的单点修改和区间求和就可以解决。

代码语言:javascript
复制
#include<cstdio>
#define N 100005
using namespace std;
int n,m,id,cnt;
int q[N],st[N],ed[N],head[N];
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;
}

树状数组

代码语言:javascript
复制
#include<cstdio>
#define N 100005
using namespace std;
int n,m,id,cnt;
int q[N],st[N],ed[N],head[N];
int cal[N],a[N];
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;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-07-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档