树上差分入门:详解+例题

树上差分

树上差分顾名思义也就是在树上做差分,一般用于区间修改操作,通过只改变区间头和区间尾来实现对整个区间值的修改。树上差分又分为点差分和边差分,一般来说要用到lca。

点差分

基本模型:有 n n n次修改操作,每次把 u − > v u->v u>v的所有点权都加 x x x,最后问点权最大的为多少。
算法分析可以先从线性的差分着手,线性差分中是 r a t e [ u ] + = x , r a t e [ v + 1 ] − = x rate[u]+=x,rate[v+1]-=x rate[u]+=x,rate[v+1]=x,之后求出的前缀和就是修改过后的数值。再回到这个问题,我们可以将 r a t e [ u ] + = x , r a t e [ v ] + = x , r a t e [ l a c ( u , v ) ] − = 2 ∗ x rate[u]+=x,rate[v]+=x,rate[lac(u,v)]-=2*x rate[u]+=x,rate[v]+=x,rate[lac(u,v)]=2x,求出子树和之后就是当前点的点权了。(注意有些题目可能会需要将边权下放为点权,下放的方法又分为两种:①直接将边权作为终点的点权。②在边的两点之间再加一个点,将这个点与两点连一条0权边,然后将原边权作为该点权值)。

这里找来一张图供大家参考

在这里插入图片描述

图片转自Sagittarius

下面边差分也要用到它

例题 —— 闇の連鎖

题目描述

传说中的暗之连锁被人们称为Dark。Dark 是人类内心的 黑暗的产物,古今中外的勇者们都试图打倒它。经过研究, 你发现Dark 呈现无向图的结构,图中有N 个节点和两类边, 一类边被称为主要边,而另一类被称为附加边。Dark 有N – 1 条主要边,并且Dark 的任意两个节点之间都存在一条只由主 要边构成的路径。另外,Dark 还有M 条附加边。

你的任务是把Dark 斩为不连通的两部分。一开始Dark 的附加边都处于无敌状态,你只能选择一条主要边切断。一 旦你切断了一条主要边,Dark 就会进入防御模式,主要边会变为无敌的而附加边可以被切 断。但是你的能力只能再切断Dark 的一条附加边。现在你想要知道,一共有多少种方案可 以击败Dark。注意,就算你第一步切断主要边之后就已经把Dark 斩为两截,你也需要切断 一条附加边才算击败了Dark。

输入格式

第一行包含两个整数N 和M。

之后N – 1 行,每行包括两个整数A 和B,表示A 和B 之间有一条主要边。

之后M 行以同样的格式给出附加边。

输出格式

输出一个整数表示答案。

样例输入

4 1
1 2
2 3
1 4
3 4

样例输出

3

数据范围与约定

对于20% 的数据, N ≤ 100 , M ≤ 100 N≤100,M≤100 N100M100

对于100% 的数据, N ≤ 100000 , M ≤ 200000 N≤100 000,M≤200 000 N100000M200000。数据保证答案不超过 2 31 – 1 2^{31 }– 1 231–1

题解

因为当 ( x , y ) (x,y) (x,y)路径上的任意一条主要边消失后,附加边都可以成为主要边,去维护连通性。
因此现在我们的问题模型转化了。给定一个 n − 1 n−1 n1条边的树,求每一条树边,被非树边覆盖了多少次。(树边也就是主要边,非树边也就是附加边)。
这其实就是一个树上差分问题:每一条附加边,使得(x,y)节点的路径上,每一个节点的权值+1。

c o d e code code

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+
  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值