【POJ 3321】dfs+树状数组

1.题目链接。题目大意:一棵树上的每一个节点在初始的时候都长了一个苹果,然后有这样的两种操作:

(1)Q x:询问以x为根节点的子树上苹果的数量

(2)C x把标号为x除的状态改变。状态改变的意思就是原来这里有苹果,就变没,原来没有就长出来一个,保证每个节点最多一个苹果。

2.首先我们肯定没有办法离线所有的操作,然后看这种点修改,区间查询,马上就想到了树状数组了。但是我们怎么把树上的信息放在树状数组上维护呢?这是一个很重要的问题。其实这个问题并不难解决,我们可以对这棵树做一遍dfs,dfs的过程中对节点编号,这样每一颗子树都一定是一个连续的区间,区间的起点就是根节点,终点是子树里面编号最大的那个节点,所以在dfs回溯的过程中维护一下这个信息,那么我们就可以把一颗子树映射成数组上一段连续的区间,然后就是点修改,区间查询的基本操作了。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<stdio.h>
#include<cmath>
#include<vector>
using namespace std;
#define ll long long
#pragma warning(disable:4996)
const ll maxn = 1e5 + 5;
int n;
int trans[maxn];
vector< vector<int> >v(maxn);
int tree[maxn], apple[maxn], Next[maxn];
int cnt = 1;
inline int lb(int x)
{
	return x & (-x);
}
void add(int x, int num)
{
	for (int i = x; i <= n; i += lb(i))
		tree[i] += num;
}
ll getsum(int x)
{
	ll ans = 0;
	for (int i = x; i > 0; i -= lb(i))
		ans += tree[i];
	return ans;
}
void dfs(int x)
{
	trans[x] = cnt++;
	for (int i = 0; i < v[x].size(); i++)
		dfs(v[x][i]);
	Next[trans[x]] = cnt - 1;
}
int main()
{
	while (~scanf("%d", &n) && n)
	{
		int a, b;
		cnt = 1;
		memset(tree, 0, sizeof(tree));
		memset(Next, 0, sizeof(Next));
		memset(trans, 0, sizeof(trans));
		for (int i = 1; i <= n; i++)
		{
			v[i].clear();
			apple[i] = 1;
			add(i, 1);
		}
		for (int i = 1; i <n; i++)
		{
			scanf("%d%d", &a, &b);
			v[a].push_back(b);
		}
		dfs(1);
		int T;
		scanf("%d", &T);
		while (T--)
		{
			char s;
			int k;
			//cin >> s >> k;
			scanf(" %c %d", &s, &k);
			int t = trans[k];
			if (s == 'Q')
			{
				ll ans = getsum(Next[t]) - getsum(t - 1);
				printf("%lld\n", ans);
			}
			else
			{
				if (apple[k] == 1)
					add(t, -1);
				else
					add(t, 1);
				apple[k] = !apple[k];
			}
		}
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值