POJ 3321 Apple Tree 树状数组

题意:给你一棵n个点,n-1条无向边的树,最初每个节点都是1,然后现在有两种操作,一种是将某个节点的值亦或1,一种是求当前节点及其下属节点的值的和。

方法:转换树状数组。

解析:如何转换树状数组呢?是应用搜索序来转换的。因为树状数组维护的是一个线性的和,而这道题恰巧可以用搜索序来映射到线性,所以采用这种办法。

可以举个例子来说明

这里写图片描述

如上图所示的树,我们对它进行搜索的时候1是第一个被遍历到的,而只有把所有的点都遍历完事后才会回溯到1,所以可见1的搜索序可以用起始端点以及结束端点即[1,5]来代表,同理,2的起始为2,结束为4,[2,4]来代表2,4就可以用[3,3],5用[4,4],3用[5,5],这样就把这棵树投影到线性了,再用树状数组就非常简便了。

代码

#include <stdio.h>
#include <string.h>
struct node
{
    int to ;
    int next ;
};
bool is_used[100001] ;
node edge[100001 * 2] ;
int head[100001] ;
char useless[5] ;
int s[100001] ;
int e[100001] ;
int c[100001] ;
int index ;
int cnt ;
int n ;
void init()
{
    memset(head , -1 , sizeof(head)) ;
    cnt = 1 ;
}
void edgeadd(int from , int to)
{
    edge[cnt].to = to ;
    edge[cnt].next = head[from] ;
    head[from] = cnt++ ;
}
void dfs(int fa , int too)
{
    s[too] = ++index ;
    for(int i = head[too] ; i != -1 ; i = edge[i].next)
    {
        int to = edge[i].to ;
        if(to != fa)
        {
            dfs(too , to) ;
        }
    }
    e[too] = index ;
}
int lowbit(int x)
{
    return x & (-x) ;
}
void updata(int x , int tmp)
{
    while(x <= n)
    {
        c[x] += tmp ;
        x += lowbit(x) ;
    }
}
int getsum(int x)
{
    int sum = 0 ;
    while(x)
    {
        sum += c[x] ;
        x -= lowbit(x) ;
    }
    return sum ;
}
int main()
{
    scanf("%d" , &n) ;
    init() ;
    for(int i = 1 ; i < n ; i++)
    {
        int x , y ;
        scanf("%d%d" , &x , &y) ;
        edgeadd(x , y) ;
        edgeadd(y , x) ;
    }
    dfs(-1 , 1) ;
    for(int i = 1 ; i <= n ; i++)
    {
        updata(i , 1) ;
        is_used[i] = 1 ;
    }
    int q ;
    scanf("%d" , &q) ;
    for(int i = 1 ; i <= q ; i++)
    {
        scanf("%s" , useless) ;
        if(useless[0] == 'C')
        {
            int x ; 
            scanf("%d" , &x) ;
            if(is_used[x] == 1)
            {
                is_used[x] = 0 ; 
                updata(s[x] , -1) ;
            }else
            {
                is_used[x] = 1 ;
                updata(s[x] , 1) ;
            }
        }else
        {
            int x ;
            scanf("%d" , &x) ;
            printf("%d\n" , getsum(e[x]) - getsum(s[x] - 1)) ;
        }
    }
}
python023基于Python旅游景点推荐系统带vue前后端分离毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值