【POJ3321】Apple Tree

Link:
POJ http://poj.org/problem?id=3321


Description


要求支持查询子树权值和。
以及单点权值取反。
一开始每个点都长了苹果(权值为1)。


Solution


处理出dfs序然后直接做。
正常的DFS序其实有点类似括号序列
但是并不需要真的这么记录

什么意思呢,就是实际上我们的程序里完全不会出现一个完整的dfs序,
只会有 in[] 跟 out[] 分别代表 第一次访问这个点的时间 和 离开这个点的时间
而这个“时间”也不是真的走一步算一次,而是现在访问过的结点数量

这样的话,DFS序里面 in[] ~ out[] 对应这个点的子树
所以对子树的修改和查询就变成区间操作。

随便找个数据结构维护一下。
哦对不起,我的线段树太丑了会tle,,,
用树状数组吧
很神奇的是这道题目给出的边保证是u深度比v小。

日常忘记return Ans
不过树状数组真短/se
啊啊啊 结果把 in[x] 和 x 搞混了


Code


#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
const int MAXN = 1e6 + 10;
int N, M, tot=0;
int head[MAXN], nxt[MAXN], to[MAXN];
int in[MAXN], out[MAXN], curtime=0;
#define add_edge(a,b) nxt[++tot]=head[a], head[a]=tot, to[tot]=b
void DFS(int pos, int fa=0)
{
	in[pos]=++curtime;
	for (int i = head[pos]; i; i=nxt[i])
	{
		if (to[i]==fa) continue;
		DFS(to[i], pos);
	}
	out[pos]=curtime;
}
//int sz[MAXN<<2];
//void Build_Tree(int pos, int l, int r)
//{
//	sz[pos] = r - l + 1;
//	if (l < r)
//	{
//		int mid = l + r >> 1;
//		Build_Tree(pos<<1, l, mid);
//		Build_Tree(pos<<1|1, mid+1, r);
//	}
//}
//void modify(int pos, int l, int r, int id)
//{
//	if (l==r)
//	{
//		 sz[pos]=!sz[pos];
//		 return;
//	}
//	int mid = l + r >> 1;
//	if (id<=mid) modify(pos<<1, l, mid, id);
//	else modify(pos<<1|1, mid+1, r, id);
//	sz[pos] = sz[pos<<1] + sz[pos<<1|1];
//}
//int ql, qr;
//int Query(int pos, int l, int r)
//{
//	if (ql <= l && qr >= r) return sz[pos];
//	if (ql > r || qr < l) return 0;
//	int mid = l + r >> 1;
//	return Query(pos<<1, l, mid) + Query(pos<<1|1, mid+1, r);
//}
#define lowbit(x) (x)&(-x)
int sz[MAXN];
int a[MAXN];
int tmp;
void modify(int x)
{
	while (x <= N)
	{
		sz[x] += tmp;
		x += lowbit(x);
	}
}
int Query(int x)
{
	static int Ans;
	Ans = 0;
	while (x)
	{
		Ans += sz[x];
		x -= lowbit(x);
	}
	return Ans;
}
int main()
{
	ios::sync_with_stdio(false);
	cin >> N;
	for (int u, v, i = 1; i < N; ++i)
	{
		cin >> u >> v;
		add_edge(u,v);
		add_edge(v,u);
	}
	cin >> M;
	DFS(1);
	for (int i = 1; i <= N; ++i)
	{
		tmp = +1;
		a[i] = 1;
		modify(i);
	}
//	Build_Tree(1, 1, N);
	char ch;
	for (int x, i = 1; i <= M; ++i)
	{
		cin >> ch >> x;
		switch(ch)
		{
			case 'C':
				tmp = a[x] ? -1 : +1;
				a[x] = !a[x];
				modify(in[x]);
				break;

			case 'Q':
				cout << Query(out[x]) - Query(in[x]-1) << endl;
				break;
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/ccryolitecc/p/13810723.html