【POJ 3321】 Apple Tree 树状数组 + DFS序(详解)

该博客详细介绍了如何利用树状数组和DFS序解决POJ 3321 Apple Tree问题。文章首先阐述了题目背景和输入输出要求,接着解释了通过DFS序将树线性化的思想,以及如何将子树苹果数量的查询转化为区间查询。最后,提供了完整的AC代码实现。
摘要由CSDN通过智能技术生成

Description

There is an apple tree outside of kaka’s house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been carefully nurturing the big apple tree.

The tree has N forks which are connected by branches. Kaka numbers the forks by 1 to N and the root is always numbered by 1. Apples will grow on the forks and two apple won’t grow on the same fork. kaka wants to know how many apples are there in a sub-tree, for his study of the produce ability of the apple tree.

The trouble is that a new apple may grow on an empty fork some time and kaka may pick an apple from the tree for his dessert. Can you help kaka?

Input

The first line contains an integer N (N ≤ 100,000) , which is the number of the forks in the tree.
The following N - 1 lines each contain two integers u and v, which means fork u and fork v are connected by a branch.
The next line contains an integer M (M ≤ 100,000).
The following M lines each contain a message which is either
“C x” which means the existence of the apple on fork x has been changed. i.e. if there is an apple on the fork, then Kaka pick it; otherwise a new apple has grown on the empty fork.
or
“Q x” which means an inquiry for the number of apples in the sub-tree above the fork x, including the apple (if exists) on the fork x
Note the tree is full of apples at the beginning

Output

For every inquiry, output the correspond answer per line.
Sample Input

3
1 2
1 3
3
Q 1
C 2
Q 1
Sample Output

3
2

题意:给一颗苹果树,有些结点通过枝叶相连,回答更新操作(对某个结点,有苹果就摘下,没有就放上),和查询操作(问一个结点及其的子树有多少苹果)

思路(DFS序 + 树状数组):

1.由于是线段树(树状数组)专题里面做到的题,会自然的想到求当前结点的子树的苹果和,就是一个【L,R】的区间查询。问题在于怎么在树上构建一个这样的线性区间呢?

在这里插入图片描述
如图,我们要求2的子树元素和

这时候,我们就要利用DFS序来实现对树的线性化了。比如,我们可以将1->2这个分支改变成一个【1,5】的区间(有5个子节点),然后3->7就是区间【6,7】,然后我们求2的子树元素和就转化为求【2,5】的区间和,同理,求3的子树和就是求【6,7】的区间和。实现到树状数组(线段树)操作的转化。而实现的过程也非常简单。我们用DFS深度遍历一遍所有结点,每走到一个点就是idx++,如1->2->4->6这一条路是最先遍历到的,序号就是1, 2, 3,4,然后退回到5结点就是idx=5,。

在这里插入图片描述

如图,将上述转化成【2,5】区间的查询。

代码实现:

void dfs_for_tree(int x)
{
   
        L[x] = ++idx; //idx初始化为0
        for(int i=0;i<D[x].size();i++)
        {
   
                vis[x] = 1;
                if(!vis[D[x][i]])
                dfs_for_tree(D[x][i
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值