dfs序模板题

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]);
	} 
	
	
	
}
发布了92 篇原创文章 · 获赞 7 · 访问量 3725

猜你喜欢

转载自blog.csdn.net/dajiangyou123456/article/details/104468783
今日推荐