dfs序的作用就是将树形结构转化成线性结构,便于区间操作
思路:
用dfs序将树形结构转换为线性结构,然后用线段树或树状数据进行维护。
当用dfs遍历这棵树的时候,进入到这个点是有一个进入时间in,递归完成后有一个退出时间to,所以这个点和它子树所在的区间就是【in[u], to[u]】(u就是这个点)。
code:
#include<iostream>
#include<stdio.h>
using namespace std;
const int maxn = 1e6 + 5;
struct node{
int v, next;
}p[maxn];
int head[maxn], in[maxn], to[maxn], vis[maxn], cnt, time;
int st[maxn << 2];
void init(int n){
for(int i = 0; i <= n; i++) head[i] = vis[i] = 0;
cnt = 0;
time = 0;
}
void add(int u, int v){ //建图
p[++cnt].v = v;
p[cnt].next = head[u];
head[u] = cnt;
}
void dfs(int u){ //建dfs序
if(vis[u]) return ;
vis[u] = 1;
in[u] = ++time;
for(int i = head[u]; i; i = p[i].next)
dfs(p[i].v);
to[u] = time;
}
void build(int o, int l, int r){
if(l == r){
st[o] = 1;
return;
}
int m = (l + r) >> 1;
st[o << 1] = st[o << 1 | 1] = 0; //初始化st数组
build(o << 1, l, m);
build(o << 1 | 1, m + 1, r);
st[o] = st[o << 1] + st[o << 1 | 1];
}
void updata(int o, int l, int r, int k){
if(l == r && l == k){
st[o] = !st[o];
return;
}
int m = (l + r) >> 1;
if(k <= m) updata(o << 1, l, m, k);
else updata(o << 1 | 1, m + 1, r, k);
st[o] = st[o << 1] + st[o << 1 | 1];
}
int query(int o, int l, int r, int L, int R){
if(L <= l && r <= R){
return st[o];
}
int m = (l + r) >> 1;
int sum = 0;
if(L <= m) sum += query(o << 1, l, m, L, R);
if(R > m) sum += query(o << 1 | 1, m + 1, r, L, R);
return sum;
}
int main(){
int n, m, u, v, y;
char x[10];
scanf("%d%d", &n, &m);
init(n); //初始化
for(int i = 1; i < n; i++){
scanf("%d%d", &u, &v);
add(u, v);
}
dfs(1);
build(1, 1, n);
for(int i = 0; i < m; i++){
scanf("%s%d", x, &y);
if(x[0] == 'Q') printf("%d\n", query(1, 1, n, in[y], to[y]));
else updata(1, 1, n, in[y]);
}
}