Apple Tree
因POJ不支持C++的新版本,因此没提交,自己造的数据都通过了。
先说题意,给你一颗树(没说二叉树),让你进行单点修改或某点的子节点数量查询。
思路:先dfs,对每个结点重新标号,然后标记其本身与子节点的范围。随后对每个节点的数量初始化为其节点范围大小。然后就可对其进行线段树的修改维护与查询了。修改时可以用异或。
代码
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string>
#include<string.h>
#include<vector>
using namespace std;
int n, m;
int a, b, idx;
char ch;
struct P {
bool val;
int cnt;
int l, r;
vector<int>v;
}tre[100005];
void dfs(int p) {
tre[p].l = ++idx;
for (auto x : tre[p].v) dfs(x);
tre[p].r = idx;
}
int built(int p,int l,int r) {
if (l==r)return tre[p].cnt = 1;
for (auto x : tre[p].v) built(x,tre[x].l,tre[x].r);
tre[p].cnt = tre[p].r - tre[p].l + 1;
}
int modify(int p, int key) {
if (p == key) {
if (tre[p].val)tre[p].cnt--;
else tre[p].cnt++;
return (tre[p].val ^= 1);
}
int ans;
for (auto x : tre[p].v) {
if (key >= tre[p].l && key <= tre[p].r) {
ans = modify(x, key);
if (ans) tre[p].cnt++;
else tre[p].cnt--;
return ans;
}
}
}
int findkey(int p, int key) {
if (p == key)return tre[p].cnt;
for (auto x : tre[p].v)
if (key >= tre[x].l && key <= tre[x].r) return findkey(x, key);
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) tre[i].val = true;
for (int i = 1; i < n; i++){
cin >> a >> b;
tre[a].v.push_back(b);
}
dfs(1); built(1, 1, n);
cin >> m;
while (m--) {
cin >> ch >> a;
if (ch == 'C')modify(1, a);
else cout << findkey(1, a) << endl;
}
return 0;
}