POJ 3321 Apple Tree 树状数组

本文介绍了一种使用树状数组解决特定树形结构中查询与更新问题的方法。通过为每个枝桠分配一个order标记,并利用树状数组记录苹果的状态,实现了高效的查询与更新操作。文中提供了一个具体的实现示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:苹果树上有很多枝桠,每个枝桠用1-N的数字标号。有一两种操作,一种是询问每个枝桠上的苹果(包括其子树),一种是改变一个枝桠(有苹果的变没苹果,没苹果的变有苹果)
做法: 参考大神
其中最重要的一个思想是用order 标记每个枝桠,这样一来,只要是在加一个up,down数组,就可以确定一个枝桠的覆盖范围。其实也可以用线段树做的,可是,正在练树状数组...
然后,因为每个节点中的苹果只要一个,所有,树状数组中的元素num[i]=i&(-i),神题,马克....
#include<cstdio>
#include<cstring>
#include<iostream>
#define LMT 100015
#define lowbit(x) x&(-x)
//主要思想,oder
using namespace std;
int up[LMT],down[LMT],num[LMT],next[LMT],order,n,all;
bool have[LMT];
struct line
{
    int u,v,next;
}e[LMT<<1];
void insert(int u,int v)
{
    e[all].u=u;
    e[all].v=v;
    e[all].next=next[u];
    next[u]=all++;
}
void init(void)
{
    memset(num,0,sizeof(num));
    memset(up,0,sizeof(up));
    memset(down,0,sizeof(down));
    memset(have,1,sizeof(have));
    memset(next,-1,sizeof(next));
    order=1;all=0;
    for(int i=0;i<=n+10;i++)num[i]=i&(-i);
}
void dfs(int u,int pre)
{
    down[u]=order;//下界
    for(int x=next[u];x!=-1;x=e[x].next)
    if(e[x].v!=pre)
    dfs(e[x].v,u);
    up[u]=order++;//上界
}
int sum(int x)
{
    int ret=0;
    while(x>0)
    {
        ret+=num[x];
        x-=lowbit(x);
    }
    return ret;
}
void update(int x,int ope)
{
    while(x<=n)
    {
       num[x]+=ope;
       x+=lowbit(x);
    }
}
int main(void)
{
    int x,m;
    scanf("%d",&n);
    init();
    for(int i=1;i<n;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        insert(u,v);
        insert(v,u);
    }
    dfs(1,-1);
    scanf("%d",&m);
    char ord[3];
    while(m--)
    {
        scanf("%s %d",ord,&x);
        if(strcmp(ord,"Q")==0)printf("%d\n",sum(up[x])-sum(down[x]-1));
        else
        {
            if(have[x])
            update(up[x],-1);
            else update(up[x],1);
            have[x]^=1;
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值