20260130树上差分总结

数列差分

定义ci=ai-ai-1,特殊的c1=a1,cn+1=-an

常用性质

  1. c1+...+cn+1的和为0。
  2. ci求前缀和会得出原始数组。
  3. 把原数组从 l 到 r 都加val,那么差分数组相当于cl+=val,cr+1-=val。

树上差分

点差分

设将树上两点A,B两点的简单路径上的点都加val。

  1. 将A到B的路径拆为A到LCA和B到LCA。
  2. 将A到LCA的路径看作一个数列,区间加val等价于cA+=val,cfa\[LCA]-=val。
  3. 同理,cB+=val,cLCA-=val。

边差分

相当于把边权放到连接的儿子节点上,那么就转换成cA+=val,cB+=val,cLCA-=val*2。

典型例题

P3128 USACO15DEC Max Flow P

板板板。

首先把LCA预处理出来,然后点差分,最后用一次dfs前缀和,求最大值输出完事。

cpp 复制代码
int ans;
void dfs1(int x,int fa){
	for(int i=0;i<E[x].size();i++){
		int v=E[x][i];
		if(v==fa)continue;
		dfs1(v,x);
		c[x]+=c[v];
	}
	ans=max(ans,c[x]);
}
int main(){
	while(k--){
		int x,y;//输入要树上差分的两个结点
		cin>>x>>y;
		int lca=LCA(x,y);//求出LCA
		c[x]++;//差分
		c[y]++;
		c[lca]--;
		c[fc[0][lca]]--;
	}
	dfs1(1,0);//前缀和
	cout<<ans;
	return 0;
}
P3258 JLOI2014 松鼠的新家

典型的一道树上差分的题,首先把LCA预处理出来,然后在a数组里找到每个两两相邻的点作树上差分,差分完求前缀和,最后因为枚举相邻点时中间节点会多放一个,且最后一个节点已经到了厨房会多放一个,所以前缀和完了后这几个节点都要减1。

cpp 复制代码
void dfs1(int x,int fa){//将差分数组前缀和,得出原本的数组 
	for(int i=0;i<E[x].size();i++){
		int v=E[x][i];
		if(v==fa)continue;
		dfs1(v,x);
		c[x]+=c[v];
	}
}
int main(){
	for(int i=2;i<=n;i++){
		int x=a[i-1],y=a[i];//将每两个相邻的点做一次树上差分
		int lca=LCA(x,y);
		c[x]++;
		c[y]++;
		c[lca]--;//点差分
		c[fc[0][lca]]--;
	}
	dfs1(1,0);
	for(int i=2;i<=n;i++){//减1大法
		c[a[i]]--;
	}
}
U143800 暗之连锁

题意:Duck 是人类内心的黑暗的产物,今古外中的勇者们都试图打倒它。

放错了:给定n个点的树有n-1条主要边,还有m条附加边,要求删除1条主要边和1条附加边,使得不连通,求方案数。

  1. 对于一条主要边(树边),若其不在环上,则第二条边随便删,共m种方法。
  2. 一条主要边恰好在一条环上,则第二条边选择唯一,贡献一种方法。
  3. 否则一条主要边在两条环以上删一条不够,贡献为0。

那么问题就转化成统计主要边在多少个环上,对于一条附加边(x,y),添加后会在树上x到y的主要边路径形成环,那么问题又变成了路径覆盖问题,考虑边差分。

cpp 复制代码
void dfs1(int x,int fa){
	for(int i=0;i<E[x].size();i++){
		int v=E[x][i];
		if(v==fa)continue;
		dfs1(v,x);
		c[x]+=c[v];
	}
}
int main(){
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		int lca=LCA(x,y);
		c[x]++;
		c[y]++;
		c[lca]-=2;//边差分
	}
	dfs1(1,0);//前缀和
	int ans=0;
	for(int i=2;i<=n;i++){//边差分,不算根节点
		if(c[i]==0){//没在任一环上
			ans+=m;
		}
		if(c[i]==1){//恰好在一环上
			ans++;
		}
	}
	cout<<ans;
	return 0;
}
相关推荐
倒头就睡的小比特2 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!2 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼2 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光2 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark2 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her12 天前
并查集-听课笔记
笔记·算法·并查集
码流子2 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven2 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark2 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218612 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法