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));
        }
    }
}
原文地址:https://www.cnblogs.com/dingmenghao/p/5765219.html