树链剖分模板

DFS1


void DFS1( int x , int f , int deep ) {
	fa[x] = f ;
	dep[x] = deep ;
	Size[x] = 1 ;
	for( int i = 0 ; i < G[x].size() ; ++ i ) {
		int s = G[x][i] ;
		if( s == f )
			continue;
		DFS1( s,x,deep+1 );
		Size[x] += Size[s] ;
		if( Size[s] > Size[son[x]] || !son[x] )
			son[x] = s ;
	}
}

DFS2


void DFS2( int x , int T ) {
	top[x] = T ;
	cnt ++ ;
	id[x] = cnt ;
	be[cnt] = x ;
	if( !son[x] )
		return ;
	DFS2( son[x] , T );
	for( int i = 0 ; i < G[x].size() ; ++ i ) {
		int s = G[x][i] ;
		if( s == son[x] || s == fa[x] )
			continue ;
		DFS2(s,s);
	}
}

LCA


int Get_sum( int x , int y ) {
	while( top[x] != top[y] ) {
		if( dep[top[x]] < dep[top[y]] )
			swap(x,y) ;
		x = fa[top[x]] ;
	}
        if( dep[x] < dep[y] )
		swap(x,y) ;
	return y ;
}

LCA树剖模板

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <map>
#define N 100005
using namespace std ;
 
int n , m , ans ;
int dep[N] , fa[N] , son[N] , Size[N] ;
int top[N] , id[N] , be[N] , cnt ;//id为点x的DFS序,be为DFS序对应的点
vector <int> G[N] ;
 
struct node {
	int l , r , sum ;
	int lazy ;
} Tree[4*N] ;
 
void pushup( int x ) {//更新
	int lson = 2*x , rson = 2*x+1 ;
	Tree[x].sum = Tree[lson].sum + Tree[rson].sum ;
}
 
void pushdown( int x ) {//下放懒标记
	if( Tree[x].lazy == 1 ) {
		Tree[x].lazy = 0 ;
		Tree[x*2].sum = Tree[x*2].r-Tree[x*2].l+1 ;
		Tree[x*2+1].sum = Tree[x*2+1].r-Tree[x*2+1].l+1 ;//更新左右儿子
		Tree[x*2].lazy = Tree[x*2+1].lazy = 1 ;
		return ;
	}
	if( Tree[x].lazy == 2 ) {
		Tree[x].lazy = 0 ;
		Tree[x*2].sum = Tree[x*2+1].sum = 0 ;//更新左右儿子
		Tree[x*2].lazy = Tree[x*2+1].lazy = 2 ;
	}
}
 
void build( int l, int r , int x ) {//建线段树
	if( l == r ) {
		Tree[x].lazy = 0 ;
		Tree[x].l = Tree[x].r = l ;
		Tree[x].sum = 0 ;
		return ;
	}
	Tree[x].sum = 0 , Tree[x].lazy = 0 ;
	Tree[x].l = l , Tree[x].r = r ;
	int mid = (l+r)/2 ;
	build(l,mid,x*2);
	build(mid+1,r,x*2+1);
	pushup(x) ;
}
 
int quary1( int l , int r , int x ) {//下载
	if( l > r )
		swap(l,r) ;
	if( l <= Tree[x].l && r >= Tree[x].r ) {
		int sum = Tree[x].sum ;
		Tree[x].sum = Tree[x].r-Tree[x].l+1 ;//下载赋值
		Tree[x].lazy = 1 ;//懒标记
		return sum ;
	}
	int mid = (Tree[x].l+Tree[x].r)/2 ;
	pushdown(x) ;//下放懒标记
	int sum = 0 ;
	if( l <= mid )
		sum += quary1(l,r,x*2) ;
	if( r >= mid+1 )
		sum += quary1(l,r,2*x+1) ;
	pushup(x) ;//更新
	return sum ;
}
 
int quary2( int l , int r , int x ) {//卸载
	if( l > r )
		swap(l,r) ;
	if( l <= Tree[x].l && r >= Tree[x].r ) {
		int sum = Tree[x].sum ;
		Tree[x].sum = 0 ;//卸载清零
		Tree[x].lazy = 2 ;//懒标记
		return sum ;
	}
	int mid = (Tree[x].l+Tree[x].r)/2 ;
	pushdown(x);//下放懒标记
	int sum = 0 ;
	if( l <= mid )
		sum += quary2(l,r,x*2) ;
	if( r >= mid+1 )
		sum += quary2(l,r,2*x+1) ;
	pushup(x) ;//更新
	return sum ;
}
 
void DFS1( int x , int f , int deep ) {
	fa[x] = f ;
	dep[x] = deep ;
	Size[x] = 1 ;
	for( int i = 0 ; i < G[x].size() ; ++ i ) {
		int s = G[x][i] ;
		if( s == f )
			continue;
		DFS1( s,x,deep+1 );
		Size[x] += Size[s] ;
		if( Size[s] > Size[son[x]] || !son[x] )
			son[x] = s ;
	}
}
 
void DFS2( int x , int T ) {
	top[x] = T ;
	cnt ++ ;
	id[x] = cnt ;
	be[cnt] = x ;
	if( !son[x] )
		return ;
	DFS2( son[x] , T );
	for( int i = 0 ; i < G[x].size() ; ++ i ) {
		int s = G[x][i] ;
		if( s == son[x] || s == fa[x] )
			continue ;
		DFS2(s,s);
	}
}
 
int Get_sum( int x , int y ) {
	int sum = 0 ;
	while( top[x] != top[y] ) {
		if( dep[top[x]] < dep[top[y]] )
			swap(x,y) ;
		sum += quary1( id[x],id[top[x]],1 );
		x = fa[top[x]] ;
	}
	sum += quary1( id[x],id[y],1 );
	return sum ;
}
 
int main() {
	scanf("%d", &n );
	for( int i = 1 ; i < n ; ++ i ) {
		int x ;
		scanf("%d", &x );
		G[i].push_back(x) ;
		G[x].push_back(i) ;
	}
	cnt = 0 ;
	DFS1(0,-1,1);
	DFS2(0,0) ;
	build(1,n,1);
	scanf("%d", &m );
	while( m -- ) {
		string Fuck ;
		cin >> Fuck ;
		int x ;
		scanf("%d", &x );
		if( Fuck[0] == 'i' ) {
			ans = Get_sum(x,0);
			printf("%d\n", dep[x]-ans );
		}
		else {
			ans = quary2( id[x] , id[x]+Size[x]-1 , 1 );
			printf("%d\n", ans ) ;
		}
	}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值