You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
2.7 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <math.h>
#include <cstdio>
using namespace std;
const int N = 1e5 + 10, M = N << 1;
//邻接表
int e[M], h[N], idx, ne[M];
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
// dfs序专用数据结构
int in[N], out[N], tot;
// dfs序模板
void dfs(int u, int fa) {
in[u] = ++tot; // dfs序中u节点进入 时间戳
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (j == fa) continue; //不走回头路
dfs(j, u);
}
out[u] = tot; // dfs序中u节点退出 时间戳
}
//线段树结构体
struct Node {
int l, r;
int sum;
} tr[N << 2];
//向上更新父节点的子树苹果和
void pushup(int u) {
tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
//构建线段树
void build(int u, int l, int r) {
tr[u] = {l, r};
if (l == r) {
tr[u].sum = 1; //最初的时候每个叶子节点上都是有苹果的
return;
}
int mid = (l + r) >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
//向上更新父节点信息
pushup(u);
}
//在以u为根的子树中修改x的值
void modify(int u, int x) {
if (tr[u].l == tr[u].r) {
tr[u].sum ^= 1; //异或就是将1变0将0变1。
return;
}
int mid = (tr[u].l + tr[u].r) >> 1;
if (x <= mid)
modify(u << 1, x);
else
modify(u << 1 | 1, x);
pushup(u);
}
//查询区间值
int query(int u, int l, int r) {
if (tr[u].l >= l && tr[u].r <= r) return tr[u].sum;
int mid = (tr[u].l + tr[u].r) >> 1;
int ans;
if (r <= mid)
ans = query(u << 1, l, r);
else if (l > mid)
ans = query(u << 1 | 1, l, r);
else
ans = query(u << 1, l, r) + query(u << 1 | 1, l, r);
return ans;
}
int main() {
int n, m;
scanf("%d", &n);
memset(h, -1, sizeof h);
for (int i = 1; i < n; i++) {
int a, b;
scanf("%d%d", &a, &b);
add(a, b), add(b, a);
}
//记录dfs序
dfs(1, 0);
//构建线段树
build(1, 1, n);
scanf("%d", &m);
while (m--) {
char op[2]; //注意一般字符都需要用char数组读入可以过滤掉空格和回车
int k;
scanf("%s%d", op, &k); //注意op按字符数组读入是不用&地址符的!
if (*op == 'C')
modify(1, in[k]); //原始第k个节点对应线段树中第in[k]个节点
else
printf("%d\n", query(1, in[k], out[k])); //查询k这个点在in[k],out[k]区间内的sum和。
}
return 0;
}