POJ-3321-Apple Tree

来源:互联网 发布:mac大写字母怎么打 编辑:程序博客网 时间:2024/06/05 00:44

题意:一棵树上有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;}


0 0