POJ 3321 Apple Tree

2016暑期集训4-G

POJ 3321 Apple Tree

线段树 dfs序

传送门:HustOJ

传送门:POJ


题意

一棵树,每一个节点(子叶节点与非子叶节点)有一个苹果。两种操作:C操作,针对某个节点,如果这个节点有苹果,就把这个苹果吃了,没有苹果就长出来一个苹果。Q操作,针对区间,查询区间苹果数。


思路

线段树维护苹果 ,注意建图时用前向星,因为这题卡vector。


代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <iomanip>
#include <string>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

using namespace std;
const int MAXN=100007;
const int MA_XN=207;
const int oo=2000000007;
const long long int loo=2000000000000000007ll;
typedef long long int ll;
typedef struct{
    int data;
    int lazy;
} Tree;
Tree sum[MAXN<<2];

typedef struct{
    int in,out;
} Dfs;
Dfs dffs[MAXN];
bool visit[MAXN];
int cnt=1;

typedef struct{
    int to,next;
} Graph;
Graph G[MAXN<<1];
int head[MAXN];

void dfs(int n)//dfs序
{
    if(!visit[n])
    {
        dffs[n].in=cnt++;
        visit[n]=true;
    }
    else
    {
        return;
    }
    for(int i=head[n];~i;i=G[i].next)
    {
        dfs(G[i].to);
    }
    if(visit[n])
    {
        dffs[n].out=(cnt-1);
    }
}

void PushUP(int rt)
{
    sum[rt].data=sum[rt<<1].data+sum[rt<<1|1].data;
}
void build(int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt].data=1;
        return;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    PushUP(rt);
}
void update(int p,int l,int r,int rt)
{
    if(l==r)
    {
        int temp=sum[rt].data;
        sum[rt].data=temp^1;
        return;
    }
    int m=(l+r)>>1;
    if(p<=m)
    {
        update(p,lson);
    }
    else
    {
        update(p,rson);
    }
    PushUP(rt);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        return sum[rt].data;
    }
    int m=(l+r)>>1;
    int res=0;
    if(L<=m)
    {
        res+=query(L,R,lson);
    }
    if(m<R)
    {
        res+=query(L,R,rson);
    }
    return res;
}

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        memset(dffs,0,sizeof(dffs));
        memset(G,0,sizeof(G));
        memset(head,-1,sizeof(head));
        memset(sum,0,sizeof(sum));
        memset(visit,0,sizeof(visit));
        cnt=1;
        int ccc=1;
        for(int i=0;i<n-1;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            G[ccc].to=b;
            G[ccc].next=head[a];
            head[a]=ccc++;
            G[ccc].to=a;
            G[ccc].next=head[b];
            head[b]=ccc++;
        }
        dfs(1);
        build(1,n,1);
        int m;
        scanf("%d",&m);
        for(int i=0;i<m;i++)
        {
            char ss[5];
            int k;
            scanf("%s%d",ss,&k);
            if(ss[0]=='Q')
            {
                int l=dffs[k].in;
                int r=dffs[k].out;
                int res=query(l,r,1,n,1);
                printf("%d\n",res);
            }
            else
            {
                update(dffs[k].in,1,n,1);
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值