【poj 3321】Apple Tree 题意&题解&代码(C++)

题目链接:
http://poj.org/problem?id=3321
题意:
给你一颗n个节点的树,每个节点开始有一个苹果,然后m次修改,每次修改使得某个节点的苹果改变,有变成没有,没有变成有。询问的是某个节点及其子树的苹果数目。
题解:
dfs序之后,单点修改区间查询,线段树与树状数组都可以。
普通的vector在这道题中迷之超时,加了个 typedef 后就不超时了,真是神奇,手写边表的话应该没什么问题。
代码:

#include
#include
#include
#include
#include
#define lson (id*2)
#define rson (id*2+1)
#define maxn (100005)
using namespace std;
int n,in[maxn],out[maxn],m,tot;
//神奇的定义方法
typedef vector<int> ve_int;
vector lin(100005);
void dfs(int x,int f)
{
    tot++;
    in[x]=tot;
    for (int i=0;iif (lin[x][i]!=f)
    dfs(lin[x][i],x);
    out[x]=tot;
}
char p[3];
int tr[4*maxn];
void pushup(int id)
{
    tr[id]=tr[lson]+tr[rson];
}
void build(int id,int l,int r)
{
    if (l>r) return ;
    if (l==r) 
    {
        tr[id]=1;
        return ;
    }
    int mid=(l+r)/2;
    build(lson,l,mid);
    build(rson,mid+1,r);
    pushup(id);
}
void exc(int id,int l,int r,int x)
{
    if (l>r) return ;
    if (l==r&&r==x)
    {
        if (tr[id]==1) tr[id]=0;
        else tr[id]=1;
        return ;
    }
    int mid=(l+r)/2;
    if (x<=mid) exc(lson,l,mid,x);
    if (x>=mid+1) exc(rson,mid+1,r,x);
    pushup(id);
}
int ans;
void query(int id,int l,int r,int L,int R)
{
    if (l>r || L>r || Rreturn ;
    if (l>=L && r<=R) 
    {
        ans+=tr[id];
        return ;
    }
    int mid=(l+r)/2;
    if (L<=mid) query(lson,l,mid,L,R);
    if (R>=mid+1) query(rson,mid+1,r,L,R);
    pushup(id);
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n-1;i++)
    {
        int tmpa,tmpb;
        scanf("%d%d",&tmpa,&tmpb);
        lin[tmpa].push_back(tmpb);
        lin[tmpb].push_back(tmpa);
    }
    dfs(1,1);
    build(1,1,tot);
    scanf("%d",&m);
    for (int i=1;i<=m;i++)
    {
        int tmp;
        scanf("%s",p);
        scanf("%d",&tmp);
        if (p[0]=='Q')
        {
            ans=0;
            //cout<
            query(1,1,tot,in[tmp],out[tmp]);
            printf("%d\n",ans);
        }
        else
        exc(1,1,tot,in[tmp]);
    }
}

你可能感兴趣的:(oi之路,poj,DERIT的博客专栏)