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;
}