树上差分(点差分/边差分)

news2024/10/3 4:44:22

树上差分一般有两种类型的题目,一种是对边进行差分,另一种就是对点进行差分

对应的操作也有两种,对边进行差分的对应操作就是给定一对节点(u,v),让我们把u到v之间路径上的边权都加val,对点进行差分的对应操作就是给定一对节点(u,v),让我们把u到v之间路径上所经过的点的点权都加val,这两种操作是类似的,但又不完全一样,下面分别讲解一下这两种问题应该如何处理。

首先先来说一下将u到v之间路径上的边权都加val应该怎么处理。

以这个图为例子,我们假如要将1到2之间路径上的边权都加val,那么我们可以将边权唯一地对应到点权上,什么意思呢?因为对于树上的任意一个节点都有其对应的深度,那么对于同一条边所连接的两个节点的深度又是不同的,所以我们可以定义一条边权为以其连接的两个节点中的深度较大的节点为根的子树中所有节点的点权和,这样我们就可以唯一地确定每条边的边权。
那么我们要是想要把1到2之间路径上的边权都加val,我们可以把1号节点和2号节点的点权都加上val,这样凡是子树中包含节点1或2的节点的权值都会对应地加上val,我们只需要回溯的过程中更新一下以每个节点为根的子树中的节点点权之和即可,但是我们可以发现1和2的最近公共祖先3点权加了2*val,但是3号节点的点权是3号节点与其父节点之间的边权,不属于1和2之间路径的边权,所以我们应该将1和2的最近公共祖先点权减少2*val。这样就完成了更新。

还有一种常见操作就是点差分,还是以上面那个图为例,我们现在要将1到2的路径上的所有节点的权值加val,那么我们定义点权和上面边差分类似,定义一个节点的点权为以节点为根的子树中所有节点的点权和,那么我们现在要想将1到2的路径上的所有节点的权值加val,我们依旧可以先将节点1、2的点权+val,然后同理我们可以发现1和2的公共祖先3的点权相当于+2*val,但由于3号节点也属于1到2的路径上的节点之一,所以我们只需要减去val即可,但是这还不算结束,因为3号节点的父亲节点不属于1到2的路径上的节点之一,但是因为3号节点的点权加了val,而3号节点又是3号节点的子树中的节点,所以我们还应该把其父亲节点的权值减去val,这样才算是操作结束。

下面给出一道对应习题及其代码:

题目连接:P3128 [USACO15DEC]Max Flow P - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

样例输入: 

5 10
3 4
1 5
4 2
5 4
5 4
5 4
3 5
4 3
4 3
1 3
3 5
5 4
1 5
3 4

样例输出:

9

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
const int N=2e5+10;
int h[N],e[N],ne[N],idx;
int f[N][25],d[N],s[N];
void add(int x,int y)
{
	e[idx]=y;
	ne[idx]=h[x];
	h[x]=idx++;
}
void dfs(int x,int fa,int dd)
{
	d[x]=dd;
	f[x][0]=fa;
	for(int i=1;i<=20;i++)
		f[x][i]=f[f[x][i-1]][i-1];
	for(int i=h[x];i!=-1;i=ne[i])
	{
		int j=e[i];
		if(j==fa) continue;
		dfs(j,x,dd+1);
	}
}
int lca(int x,int y)
{
	if(d[x]<d[y]) swap(x,y);
	for(int i=20;i>=0;i--)
	if(d[f[x][i]]>=d[y]) x=f[x][i];
	if(x==y) return x;
	for(int i=20;i>=0;i--)
	if(f[x][i]!=f[y][i])
	{
		x=f[x][i];
		y=f[y][i];
	}
	return f[x][0];
}
void update(int x,int fa,int &ans)
{
	for(int i=h[x];i!=-1;i=ne[i])
	{
		int j=e[i];
		if(j==fa) continue;
		update(j,x,ans);
		s[x]+=s[j];
	}
	ans=max(ans,s[x]);
}
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		h[i]=-1;
	for(int i=1;i<n;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);add(y,x);
	}
	dfs(1,0,1);
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		int t=lca(x,y);
		s[x]++;s[y]++;
		s[t]--;
		s[f[t][0]]--;
	}
	int ans=0;
	update(1,0,ans);
	printf("%d",ans);
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/436671.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

经验正交分解EOF的Matlab的实现示例

在地学中&#xff0c;PCA和EOF通常用于信号提取&#xff0c;从繁杂的时空数据中分离出地理要素的时空变化特征&#xff0c;是进行地学信号分析的前提。本质上PCA和EOF没有什么不同&#xff0c;只是&#xff1a;EOF为空间特征向量&#xff0c;也称为空间模态&#xff0c;在一定程…

信号完整性分析:关于传输线的三十个问题解答(一)

1.什么是真正的传输线&#xff1f;&#xff08;What is a real transmission line?&#xff09; 答&#xff1a;真正的传输线由任意两条延长一定长度的导体组成。将一根导线标记为信号路径&#xff0c;将另一根导线标记为返回路径。 A real transmission line is composed o…

2023最经典的Python接口自动化测试中的用例编写问题总结

本篇文章分享几个接口自动化用例编写过程遇到的问题总结&#xff0c;希望能对初次探索接口自动化测试的小伙伴们解决问题上提供一小部分思路。 B站讲的最详细的Python接口自动化测试实战教程全集&#xff08;实战最新版&#xff09;_哔哩哔哩_bilibiliB站讲的最详细的Python接…

4月,不要跳槽...

跳槽是每个人都可能面临的选择&#xff0c;但不同的时间点会对跳槽带来不同的影响。对于软件测试人员来说&#xff0c;4月份并不是最适合的跳槽时间。原因如下&#xff1a; 与企业目标和计划相关。一般情况下&#xff0c;公司在1月份会制定本年度的发展目标和计划&#xff0c;而…

力扣sql中等篇练习(五)

力扣sql中等篇练习(五) 1 股票的资本收益 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 # 每个用户的所有Sell的price值减去Buy的price值就可以了 SELECT stock_name,SUM(IF(operationBuy,price*-1,price)) capital_gain_loss FROM Stocks GROUP B…

IT知识百科:什么是SSID?

一、什么是SSID SSID&#xff08;Service Set Identifier&#xff09;是无线网络中的一个重要概念&#xff0c;它是一个用于标识无线局域网&#xff08;WLAN&#xff09;的名称。SSID可以看作是无线网络的名称&#xff0c;类似于有线网络中的网络名称或者路由器的名称。在无线…

【JavaScript】5.JavaScript内置对象

JavaScript 内置对象 JavaScript 中的对象分为3种 自定义对象内置对象浏览器对象 前面两种对象是JS 基础 内容&#xff0c;属于 ECMAScript&#xff1b; 第三个浏览器对象属于JS 独有的 内置对象就是指 JS 语言自带的一些对象&#xff0c;这些对象供开发者使用&#xff0c;…

数据通信基础 - 数据通信方式

文章目录 1 概述2 分类2.1 按通信方向分2.2 按同步方式分 3 扩展3.1 网工软考真题 1 概述 分类维度分类解释举例通信方向单工通信信息 只能在一个方向发送&#xff0c;发送方不能接收&#xff0c;接收方不能发送电视、广播半双工通信通信双方可以 交替发送和接收信息&#xff…

分布式锁+AOP实现缓存

分布式锁AOP实现缓存 1、分布式锁AOP实现思想2、不使用AOP的情况2.1 没有使用缓存时代码2.2 使用Redis实现分布式锁的代码2.3 使用Redisson实现分布式锁2.4 测试缓存命中2.5 存在问题 3、分布式锁AOP实现3.1 定义注解3.2 定义一个切面类加上注解3.3 使用注解完成缓存 1、分布式…

函数的缺省参数,函数重载与底层函数名修饰解释,引用的初步介绍

TIPS 使用C输入输出更方便&#xff0c;不需要像printf/scanf输入输出时那样&#xff0c;需要手动控制格式。C的输入输出可以自动识别变量类型。在日常练习中&#xff0c;建议直接using namespace std即可&#xff0c;这样就很方便。using namespace std展开&#xff0c;标准库…

ReetrantLock源码剖析_03公平锁、非公平锁

一直努力就会有offer&#xff0c;一直努力就会有offer&#xff0c;一直努力就会有offer&#xff01; 文章目录 ReetrantLock公平锁代码解析ReetrantLock公平锁执行流程ReetrantLock非公平锁代码解析ReetrantLock非公平锁执行流程公平锁与非公平锁的比较 ReetrantLock公平锁代码…

前端部署发布项目后,如何通知用户刷新页面、清除缓存

以下只是一些思路&#xff0c;有更好的实现方式可以留言一起交流学习 方式一&#xff1a;纯前端 在每次发布前端时&#xff0c;使用webpack构建命令生成一个json文件&#xff0c;json中写个随机生成的一个字符串&#xff08;比如时间戳&#xff09;&#xff0c;每次打包程序都…

【Python入门第五十天】Python丨NumPy 数组搜索

搜索数组 可以在数组中搜索&#xff08;检索&#xff09;某个值&#xff0c;然后返回获得匹配的索引。 要搜索数组&#xff0c;请使用 where() 方法。 实例 查找值为 4 的索引&#xff1a; import numpy as nparr np.array([1, 2, 3, 4, 5, 4, 4])x np.where(arr 4)pri…

node可以用nvm快速切换版本,golang如何快速切换版本?用gvm就行。

使用 gvm 可以带来以下好处&#xff1a; 快速切换 Golang 版本&#xff0c;方便进行版本测试和开发&#xff1b;可以在多个项目中同时使用不同版本的 Golang 包和工具&#xff0c;避免冲突&#xff1b;可以通过 gvm 管理不同版本的 Golang&#xff0c;方便安装、卸载和更新&am…

STL--vector

一、vector介绍 vector是表示大小可以更改的数组的序列容器 就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问&#xff0c;和数组一样高效。但是又不像数组&#xff0c;它的大小是可以动态改变的&#xff0c;而…

移动端屏幕适配

文章目录 移动端屏幕适配移动端屏幕适配和响应式布局区别基本知识简单屏幕适配 移动端屏幕适配 移动端屏幕适配和响应式布局区别 移动端适配响应式布局终端移动端PC端和移动端常用单位宽高&#xff1a;rem 或 %字体&#xff1a;px宽&#xff1a;%高、字体&#xff1a;px宽高宽…

Docker网络模式与cgroups资源控制

目录 1.docker网络模式原理 2.端口映射 3.Docker网络模式&#xff08;41种&#xff09; 1.查看docker网络列表 2.网络模式详解 4.Docker cgroups资源控制 1.CPU资源控制 2.对内存使用的限制 3.对磁盘IO的配置控制&#xff08;blkio&#xff09;的限制 4.清除docker占用…

Vue3教程

文章目录 参考资料1 setup语法糖1.1 vue2中的写法1.2 setup语法糖在vue3中使用 2 ref reactive 事件2.1 ref2.2 reactive2.3 事件&#xff1a;在setup script中&#xff0c;直接定义事件&#xff0c;不需要像vue2那样在method中定义 3 computed & watch & watchEffect3…

详解DHCP和DNS实验汇总

文章目录 1.实验说明2.实验步骤2.1&#xff08;linux的CentOS 7-2&#xff09;命令配置2.2 &#xff08;linux的CentOS 7-3&#xff09;命令配置2.3 客户端(WIN10)命令配置2.4 客户端(CentOS 7-1)命令配置 1.实验说明 实验要求&#xff1a;要求在一台主机中同时配置DNS服务器和…

【SpringCloud】1、Nacos注册中心、配置中心搭建

1、Nacos 简介 Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字母简称&#xff0c;一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集&#xff0c;帮助…