poj 3321 Apple Tree

来源:互联网 发布:上虞司法拍卖淘宝网 编辑:程序博客网 时间:2024/05/16 18:24
  觉得挺好的一道题,就照着书打了一遍,卡人的地方还挺多的。
#include<iostream>#include<cstring>#include<stdio.h>#define max 100002using namespace std;struct node1//边表为edge,其中第i条边相连的节点为edge[i].tail;//连接的下条边的序号为edge[i].next{    int next,tail;} edge[max];struct node2//苹果树为apple,以节点i为根的子树在后根序列中的区间为{    int r,l;} apple[max];int s[max],cnt,c[max],a[max];//后根遍历中第i个节点的权值为a[i];后根遍历序号为cnt;//树状数组为c;节点i相连的第i条边的序号为s[i]//从节点u出发,计算 每个节点为根的子树区间[apple[].l,apple[].r];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++;}inline int lowbit(int x){    return x&(-x);}void change(int x)//从a[x]出发,调整树状数组{    int i;    if(a[x])//若a序列的第x个元素非零,则树状数组的相关元素值+1//否则树状数组的相关元素值-1        for(i=x; i<cnt; i+=lowbit(i))            c[i]++;    else//若权值和为x的子树根上的苹果被吃掉,则其通往根的路径上每棵子树的权值和-1        for(i=x; i<cnt; i+=lowbit(i))            c[i]--;}int sum(int x){    int i,res=0;    for(i=x; i>0; i-=lowbit(i))        res+=c[i];    return res;}int main(){    int i,n,m,t1,t2,t;    char str[3];    scanf("%d",&n);    memset(s,-1,sizeof(s[0])*(n+1));    memset(c,0,sizeof(c[0])*(n+1));    memset(apple,0,sizeof(apple[0])*(n+1));    for(i=0; i<n-1; i++)    {        scanf("%d%d",&t1,&t2);        edge[i].tail=t2;//第i条边连接t2,其后继指针指向t1连接的上一条边        edge[i].next=s[t1];        s[t1]=i;//设节点t1连接的边序号i;    }    cnt=1;    DFS(1);//从节点1出发进行DFS,计算每个节点的在后根遍历的顺序值,节点权值设1    scanf("%d",&m);//读信息数    for(i=1; i<=n; i++)//构造长满苹果的树上对应的树状数组c    {        a[i]=1;//设a[i]为1,由此出发调整树状数组        change(i);    }    while(m--)    {        scanf("%s%d",&str,&t);//读命令标志str和节点序号t        if(str[0]=='Q')//输出节点t上的苹果数            printf("%d\n",sum(apple[t].r)-sum(apple[t].l-1));        else        {//计算节点t上苹果的变化情况            a[apple[t].r]=(a[apple[t].r]+1)%2;//节点t上的苹果数由1变成0或由0变成1            change(apple[t].r);        }    }    return 0;}


  
0 0