POJ-3321-Apple Tree

题意:一棵树上有n个叉子(其实就是n个节点),再告诉你n-1个线段告诉你是u和v节点相连的,再输入m组操作,有两种操作,当是Q操作时你就要输出对象的节点上有多少个苹果(初始化时每个节点都有苹果),C操作是吃掉苹果或是长出苹果(一个节点只能是有一个苹果或是没有苹果,即:有苹果就是吃掉当前节点的苹果,没苹果就是长出苹果)。

思路:可以把它倒过来就可以用树状数组做了,就是还要用dfs来搜一下每个节点的分支有多少个,开始的时间和结束的时间就可以了。

AC代码:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=100005;
struct node1
{
    int next;
    int tail;
}edge[maxn];      //这结构体是表示第i条边的下一条边的编号和这条边所连的节点
struct node2
{
    int l,r;
}apple[maxn];     //苹果树表示i节点的开始时间个终止时间
int s[maxn],cnt,c[maxn],a[maxn];   //s存储的是i节点的分支数,cnt是总共的节点数,c数组是树状数组,a是树状数组的每个节点的权值(1或是0)
void dfs(int u)
{
    int i;
    apple[u].l=cnt;
    for(i=s[u];i!=-1;i=edge[i].next)
        dfs(edge[i].tail);
    apple[u].r=cnt++;
}
int lowbit(int x)
{
    return x&(-x);
}
void change(int x)
{
    int i;
    if(a[x])
        for(i=x;i<cnt;i+=lowbit(i))
        c[i]++;
    else
        for(i=x;i<cnt;i+=lowbit(i))
        c[i]--;
}
int sum(int x)
{
    int res=0;
    while(x)
    {
        res+=c[x];
        x-=lowbit(x);
    }
    return res;
}
int main()
{
    int n,m,t1,t2,t;
    char str[5];
    scanf("%d",&n);
    memset(s,-1,sizeof(s));
    memset(apple,0,sizeof(apple));
    memset(c,0,sizeof(c));
    for(int i=0;i<n-1;i++)
    {
        scanf("%d%d",&t1,&t2);
        edge[i].tail=t2;
        edge[i].next=s[t1];
        s[t1]=i;
    }
    cnt=1;
    dfs(1);
    scanf("%d",&m);
    for(int i=1;i<=n;i++)     //初始化每个节点的权值都是1
    {
        a[i]=1;
        change(i);
    }
    while(m--)
    {
        scanf("%s%d",&str,&t);
        if(str[0]=='Q')
            printf("%d\n",sum(apple[t].r)-sum(apple[t].l-1));
        else
        {
            a[apple[t].r]=(a[apple[t].r]+1)%2;    //权值只能是0和1   所以对2取余
            change(apple[t].r);
        }
    }
    return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值