OI模板 树链剖分

OI模板 树链剖分

重链剖分-查、改路径、子树点权

const int N = 1;
int Son[N], Nid[N], cnt, Fa[N], Dep[N], Siz[N], Top[N];
//重儿子、新编号、新编号计数、父节点、深度、子树大小、链顶端节点 
int Wegt[N], Nwet[N], Head[N], Edge[N], Next[N], tot;
//点权、新编号点权、链式前向星 
struct Node{ int sum, lazy, l, r; } T[N*4];
int n, m, rt, mod;

void addedge(int u, int v){
	Edge[++tot] = v, Next[tot] = Head[u], Head[u] = tot;
}
void update(int p){
	T[p].sum = (T[p<<1].sum + T[p<<1|1].sum) % mod;
}
void spread(int p){
	if(T[p].lazy){
		T[p<<1].sum += T[p].lazy * (T[p<<1].r - T[p<<1].l + 1);
		T[p<<1|1].sum += T[p].lazy * (T[p<<1|1].r - T[p<<1|1].l + 1);
		T[p<<1].lazy += T[p].lazy;
		T[p<<1|1].lazy += T[p].lazy;
		T[p].lazy = 0;
	}
}
void buildtree(int p, int l, int r){
	T[p].l = l, T[p].r = r;
	if(l == r){ T[p].sum = Nwet[l] % mod; return; }
	int mid = l + r >> 1;
	buildtree(p << 1, l, mid);
	buildtree(p << 1 | 1, mid + 1, r);
	update(p);
}
void change(int p, int l, int r, int v){
	if(l <= T[p].l && T[p].r <= r){
		T[p].sum = (T[p].sum + v * (T[p].r - T[p].l + 1)) % mod;
		T[p].lazy += v;
	} else {
		int mid = T[p].l + T[p].r >> 1;
		spread(p);
		if(l <= mid) change(p << 1, l, r, v);
		if(mid < r) change(p << 1 | 1, l, r, v);
		update(p);
	}
}
int query(int p, int l, int r){
	if(l <= T[p].l && T[p].r <= r) return T[p].sum % mod;
	int mid = T[p].l + T[p].r >> 1, res = 0;
	spread(p);
	if(l <= mid) res = (res + query(p << 1, l, r)) % mod;
	if(mid < r) res = (res + query(p << 1 | 1, l, r)) % mod;
	return res;
}
void dfs1(int x, int fa){
	//get Son[N], Fa[N], Dep[N], Siz[N]
	Dep[x] = Dep[fa] + 1, Fa[x] = fa, Siz[x] = 1;
	int maxson = -1;
	for(int i = Head[x]; i; i = Next[i]){
		int y = Edge[i];
		if(y == fa) continue;
		dfs1(y, x);
		Siz[x] += Siz[y];
		if(Siz[y] > maxson) Son[x] = y, maxson = Siz[y];
	}
}
void dfs2(int x, int top){
	//get Nid[N], Top[N], Nwet[N]
	Nid[x] = ++ cnt, Nwet[cnt] = Wegt[x], Top[x] = top;
	if(!Son[x]) return;
	dfs2(Son[x], top);
	for(int i = Head[x]; i; i = Next[i]){
		int y = Edge[i];
		if(y == Fa[x] || y == Son[x]) continue;
		dfs2(y, y);
	}
}
void Init(){
	dfs1(rt, 0), dfs2(rt, rt);
	buildtree(1, 1, n);
}
void UpdateRange(int x, int y, int k){
	k %= mod;
	while(Top[x] != Top[y]){
		if(Dep[Top[x]] < Dep[Top[y]]) swap(x, y);
		change(1, Nid[Top[x]], Nid[x], k);
		x = Fa[Top[x]];
	}
	if(Dep[x] > Dep[y]) swap(x, y);
	change(1, Nid[x], Nid[y], k);
} 
int QueryRange(int x, int y){
	int ans = 0;
	while(Top[x] != Top[y]){
		if(Dep[Top[x]] < Dep[Top[y]]) swap(x, y);
		ans = (ans + query(1, Nid[Top[x]], Nid[x])) % mod;
		x = Fa[Top[x]];
	}
	if(Dep[x] > Dep[y]) swap(x, y);
	return (ans + query(1, Nid[x], Nid[y])) % mod;
}
void UpdateSon(int x, int k){
	change(1, Nid[x], Nid[x] + Siz[x] - 1, k);
}
int QuerySon(int x){
	return query(1, Nid[x], Nid[x] + Siz[x] - 1);
}

例题:Luogu P3384 【模板】轻重链剖分/树链剖分

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值