zoukankan      html  css  js  c++  java
  • POJ3321 Apple Tree

    题目大意

    有一颗苹果树,它有N个树叉,每个树叉最开始的时候都结了一个苹果,有时卡卡会从树上把某个苹果摘下来,有时没结苹果的树叉上又会长出苹果来,卡卡有时还想知道某个子树的总苹果数量有多少

    题解

    题目也是要求实现单点加减,区间求和的功能,赤裸裸的树状数组呀,不过此题给出的不是一个线性的序列,而是树形的,因此我们需要先进行预处理,把树转换为线性序列。用邻接表建立好树,然后对树进行重新编号,这个可以用DFS来实现,每个节点记录第一次访问和最后一次访问时的编号,假设为l和r,那么区间[l,r]之间的所有编号是以此节点为根节点的子树的各个节点的编号,这样就把树转化为线性结构了,之后就是用树状数组来处理了

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define MAXN 100005
    using namespace std;
    typedef struct
    {
        int adv;
        int next;
    } NODE;
    NODE edg[2*MAXN];
    int head[MAXN],c[MAXN],low[MAXN],high[MAXN];
    bool visit[MAXN];
    int n,m,k,step=0;
    int lowbit(int x)
    {
        return x&-x;
    }
    int sum(int x)
    {
        int ret=0;
        while(x>0)
        {
            ret+=c[x];
            x-=lowbit(x);
        }
        return ret;
    }
    void add(int x,int d)
    {
        while(x<=n)
        {
            c[x]+=d;
            x+=lowbit(x);
        }
    }
    void addege(int u,int v)
    {
        edg[k].adv=v;
        edg[k].next=head[u];
        head[u]=k++;
    }
    void dfs(int u)
    {
        int i;
        low[u]=++step;
        visit[u]=true;
        for(i=head[u]; i!=-1; i=edg[i].next)
            if(!visit[edg[i].adv])
                dfs(edg[i].adv);
        high[u]=step;
    }
    int main(void)
    {
        int i,u,v;
        bool f[MAXN];
        char ch;
        memset(head,-1,sizeof(head));
        memset(visit,false,sizeof(visit));
        memset(f,false,sizeof(f));
        scanf("%d",&n);
        k=1;
        for(i=1; i<n; i++)
        {
            scanf("%d%d",&u,&v);
            addege(u,v);
            add(i,1);
        }
        add(i,1);
        dfs(1);
        scanf("%d",&m);
        while(m--)
        {
            getchar();
            scanf("%c%d",&ch,&i);
            if(ch=='C')
            {
                if(!f[i])
                {
                    add(low[i],-1);
                    f[i]=true;
                }
                else
                {
                    add(low[i],1);
                    f[i]=false;
                }
            }
            else
                printf("%d\n",sum(high[i])-sum(low[i]-1));
        }
        return 0;
    }

     

     

     

  • 相关阅读:
    成功连上数据库顿感世界美好许多
    MySQL数据库基本命令
    杭电1004 Let the Balloon Rise
    大数学习笔记
    安卓传感器开发之指南针
    java Class文件内部结构解析
    mysq数据库实战小型管理系统
    JSplitPane分隔线的用法
    swing 菜单+右键菜单+二级菜单实现
    input type=file 上传文件,同一个文件第二次上传无反应
  • 原文地址:https://www.cnblogs.com/zjbztianya/p/3036884.html
Copyright © 2011-2022 走看看