zoukankan      html  css  js  c++  java
  • poj3321(codevs1228)苹果树

    1228 苹果树

     

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 钻石 Diamond
     
     
     
    题目描述 Description

    在卡卡的房子外面,有一棵苹果树。每年的春天,树上总会结出很多的苹果。卡卡非常喜欢吃苹果,所以他一直都精心的呵护这棵苹果树。我们知道树是有很多分叉点的,苹果会长在枝条的分叉点上面,且不会有两个苹果结在一起。卡卡很想知道一个分叉点所代表的子树上所结的苹果的数目,以便研究苹果树哪些枝条的结果能力比较强。

    卡卡所知道的是,每隔一些时间,某些分叉点上会结出一些苹果,但是卡卡所不知道的是,总会有一些调皮的小孩来树上摘走一些苹果。

    于是我们定义两种操作:

    C x

    表示编号为x的分叉点的状态被改变(原来有苹果的话,就被摘掉,原来没有的话,就结出一个苹果)

    G x

    查询编号为x的分叉点所代表的子树中有多少个苹果

    我们假定一开始的时候,树上全都是苹果,也包括作为根结点的分叉1。

    输入描述 Input Description

    第一行一个数N (n<=100000)

    接下来n-1行,每行2个数u,v,表示分叉点u和分叉点v是直接相连的。

    再接下来一行一个数M,(M<=100000)表示询问数

    接下来M行,表示询问,询问的格式如题目所述Q x或者C x

    输出描述 Output Description

    对于每个Q x的询问,请输出相应的结果,每行输出一个

    样例输入 Sample Input

    3

    1 2

    1 3

    3

    Q 1

    C 2

    Q 1

    样例输出 Sample Output

    3

    2

    数据范围及提示 Data Size & Hint
    /*
    暴力做的,记录每个点的父亲更改一个点后,
    这个点一直到根节点全部更新codevs 1228 苹果树上得了90分
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 100010
    using namespace std;
    int n,m,topt,sum[maxn],fa[maxn],first[maxn],f[maxn];
    bool p[maxn];
    struct edge
    {
        int from;
        int to;
        int next;
    }e[maxn*2];
    int init()
    {
        int x=0,f=1;
        char c=getchar();
        while(c<'0'||c>'9')
        {
            if(c=='-')f=-1;
            c=getchar();
        }
        while(c>='0'&&c<='9')
        {
            x=x*10+c-'0';
            c=getchar();
        }
        return x*f;
    }
    void add(int x,int y)
    {
        topt++;
        e[topt].from=x;
        e[topt].to=y;
        e[topt].next=first[x];
        first[x]=topt;
    }
    void build(int x)
    {
        f[x]=1;
        int tot=1;
        for(int i=first[x];i;i=e[i].next)
        {
            int t=e[i].to;
            if(!f[t])
            {
                fa[t]=x;
                build(t);
                tot+=sum[t];
            }
        }
        sum[x]=tot;
    }
    void change(int x)
    {
        sum[x]--;
        if(fa[x])
        change(fa[x]);
    }
    int main()
    {
        int i,j,k;
        n=init();
        for(i=1;i<=n-1;i++)
        {
            int x,y;
            x=init(),y=init();
            add(x,y);add(y,x);
        }
        build(1);
        m=init();
        for(i=1;i<=m;i++)
        {
            char c;
            cin>>c;
            if(c=='C')
            {
                int x;
                x=init();
                if(!p[x])
                {
                    p[x]=1;
                    change(x);
                }
            }
            else
            if(c=='Q')
            {
                int x;
                cin>>x;
                cout<<sum[x]<<endl;
            }
        }
    }

    /*
    正解:
    dfs序+树状数组
    先dfs求出每个点最左和最右在dfs到的顺序

    那么左边和右边的之间的就是以这个点为根的子树
    修改只修改 左边change(左边) 
    查询 find(右边)-find(左边-1)就可以了*/
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 100010
    using namespace std;
    int n,m,topt,tot,t[maxn*4],first[maxn],f[maxn],l[maxn],r[maxn];
    bool p[maxn];
    char c[10];
    struct edge
    {
        int from;
        int to;
        int next;
    }e[maxn*2];
    int init()
    {
        int x=0,f=1;
        char c=getchar();
        while(c<'0'||c>'9')
        {
            if(c=='-')f=-1;
            c=getchar();
        }
        while(c>='0'&&c<='9')
        {
            x=x*10+c-'0';
            c=getchar();
        }
        return x*f;
    }
    void add(int x,int y)
    {
        topt++;
        e[topt].from=x;
        e[topt].to=y;
        e[topt].next=first[x];
        first[x]=topt;
    }
    void build(int x)
    {
        l[x]=++tot;
        f[x]=1;
        for(int i=first[x];i;i=e[i].next)
        {
            int t=e[i].to;
            if(!f[t])
            build(t);
        }
        r[x]=++tot;
    }
    void change(int k,int z)
    {
        while(k<=tot)
        {
            t[k]+=z;
            k+=k&(-k);
        }
    }
    int find(int k)
    {
        int ans=0;
        while(k)
        {
            ans+=t[k];
            k-=k&(-k);
        }
        return ans;
    }
    int main()
    {
        int i,j,k;
        n=init();
        for(i=1;i<=n-1;i++)
        {
            int x,y;
            x=init(),y=init();
            add(x,y);add(y,x);
        }
        build(1);
        for(i=1;i<=n;i++)
        change(l[i],1);
        m=init();
        for(i=1;i<=m;i++)
        {
            scanf("%s",c);
            if(c[0]=='C')
            {
                int x;
                x=init();
                if(!p[x])
                {
                    p[x]=1;
                    change(l[x],-1);
                }
                else
                {
                    p[x]=0;
                    change(l[x],1);
                }
            }
            else
            if(c[0]=='Q')
            {
                int x;
                x=init();
                printf("%d
    ",find(r[x])-find(l[x]-1));
            }
        }
    }
  • 相关阅读:
    列“XAxisBacklas”不属于表 Table。
    无经意中收看了《微软英雄》片段
    书编程(Asp.net)
    Runtime Error
    书编程(其他)
    书英语书
    【转】CodeBlocks中文版使用手册
    Java关键字this、super使用总结(转)
    分析对比主流Bootloader的性能
    C语言指针的初始化和赋值
  • 原文地址:https://www.cnblogs.com/dingmenghao/p/5765219.html
Copyright © 2011-2022 走看看