POJ 3321 Apple Tree 树状数组+dfs序

题目:http://poj.org/problem?id=3321

题意:给出一个苹果树,开始每个节点都有一个苹果,有2个操作

C:有苹果就吃掉,没有就会长出一个苹果

Q:查询包括x的子树上苹果的个数

这个题目的关键就是怎么把它从一颗树转化成一个数组

可以用dfs序重新编号,保存节点所维护的区间,然后用树状数组可以解决了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
const int N=1e5+5;
struct p
{
    int to,nextt;
};
p a[N*2];
int tot,n;
int f[N],l[N],r[N],bit[N];
bool vis[N];
void addedge(int u,int v)
{
    a[tot].to=v;
    a[tot].nextt=f[u];
    f[u]=tot++;
}
void dfs(int x)
{
    tot++;
    l[x]=tot;
    vis[x]=1;
    for(int i=f[x];i!=-1;i=a[i].nextt)
        if (!vis[a[i].to])
            dfs(a[i].to);
    r[x]=tot;
}
void add(int i,int x)
{
    while(i<=n)
    {
        bit[i]+=x;
        i+=i&-i;
    }
}
int sum(int i)
{
    int s=0;
    while(i>0)
    {
        s+=bit[i];
        i-=i&-i;
    }
    return s;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        int x,y;
        tot=0;
        memset(f,-1,sizeof(f));
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            addedge(x,y);
            addedge(y,x);
        }
        tot=0;
        memset(vis,0,sizeof(vis));
        dfs(1);
        memset(bit,0,sizeof(bit));
        for(int i=1;i<=n;i++)
            add(i,1);
        memset(vis,1,sizeof(vis));
        int m;
        char c;
        scanf("%d",&m);
        while(m--)
        {
            scanf(" %c%d",&c,&x);
            if (c=='Q')
                printf("%d
",sum(r[x])-sum(l[x]-1));
            else
            {
                if (vis[x])
                {
                    vis[x]=0;
                    add(l[x],-1);
                }
                else
                {
                    vis[x]=1;
                    add(l[x],1);
                }
            }
        }
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/bk-201/p/7445777.html