zoukankan      html  css  js  c++  java
  • 【POJ 3321】Apple Tree

    有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[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
    ",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[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
    ",getsum(ed[x])-getsum(st[x]-1));
        }
        return 0;
    }

      

  • 相关阅读:
    739. Daily Temperatures
    556. Next Greater Element III
    1078. Occurrences After Bigram
    1053. Previous Permutation With One Swap
    565. Array Nesting
    1052. Grumpy Bookstore Owner
    1051. Height Checker
    数据库入门及SQL基本语法
    ISCSI的概念
    配置一个IP SAN 存储服务器
  • 原文地址:https://www.cnblogs.com/flipped/p/5705948.html
Copyright © 2011-2022 走看看