差分之间,性质多多——差分综合应用学习笔记

差分,能够巧妙地维护多种区间修改,将区间修改转化为单点修改,将询问转化为前缀查询。

但是,差分能支持的,岂止是这些。有时,差分一下,性质多多。

例1. [Luogu P4552]IncDec Sequence

Description

给定一个序列,请求出至少需要多少次区间统加 1 1 1或区间统减 1 1 1的操作才能使得整个序列中的数两两相同。

为了增加难度,你也需要求出,在满足操作次数最小且最终序列中的数两两相同的前提下,最终能够得到多少种不同的序列。

Solution

本题中有区间修改这一说。不难想到差分。

现在,我们完成了一个重要的转化: 给定一个长度为 n + 1 n+1 n+1的序列,每次可以选择序列中的任两个位置,一个加 1 1 1,另一个减 1 1 1,使得这个序列的第 2 − n 2-n 2n个位置均为 0 0 0

由于我们要让操作次数尽可能得小,我们要先贪心地去选择在 [ 2 , n ] [2,n] [2,n]区间内的一个正数和一个负数并将它们配对,正数减 1 1 1,负数加 1 1 1。经过了这些操作之后,我们再将剩下的数去与 1 , n + 1 1,n+1 1,n+1中的一个数配对。假设这个数为正,那么配对之后它一定要减 1 1 1;否则一定要加 1 1 1。经历这些操作之后,我们便完成了要求。

假设 2 − n 2-n 2n这些数中,正数之和为 x x x,负数的绝对值之和为 y y y。首先,我们使用了 m i n ( x , y ) min(x,y) min(x,y)次操作,每次操作将一个正数减 1 1 1,一个负数加 1 1 1。然后,我们使用了 m a x ( x , y ) − m i n ( x , y ) max(x,y)-min(x,y) max(x,y)min(x,y)次操作,将每一个 [ 2 , n ] [2,n] [2,n]区间内不为 0 0 0的数与下标为 1 1 1 n + 1 n+1 n+1中的一个数配对。于是我们总共使用了 m a x ( x , y ) max(x,y) max(x,y)次操作。由于第一个位置有 m a x ( x , y ) − m i n ( x , y ) + 1 max(x,y)-min(x,y)+1 max(x,y)min(x,y)+1种不同的值(即,对于剩下的 m a x ( x , y ) − m i n ( x , y ) max(x,y)-min(x,y) max(x,y)min(x,y)都可以与下标为 1 1 1的位置配对或不与它配对),所以两个答案分别为:

m a x ( x , y ) max(x,y) max(x,y)
m a x ( x , y ) − m i n ( x , y ) + 1 max(x,y)-min(x,y)+1 max(x,y)min(x,y)+1

时间复杂度 O ( n ) O(n) O(n)。本题得到完美解决。

Summary

我们通过差分,将区间修改转化为单点修改,自然而然得到了几个性质,从而推出结论。

例2. [LNOI2014]LCA

Description

给定一棵包含 n n n个节点的树, q q q次询问,每次给定 l , r , x l,r,x l,r,x,请你求出 ∑ i = l r d e p t h ( L C A ( i , x ) ) \sum_{i=l}^r depth(LCA(i,x)) i=lrdepth(LCA(i,x))

这里的 d e p t h depth depth表示一个节点的深度,即其与根节点的距离 1 1 1

Solution

一道绝妙的好题。

首先,我们考虑 d e p t h ( L C A ( i , x ) ) depth(LCA(i,x)) depth(LCA(i,x))等于什么。在这之前,我们先思考 d e p t h depth depth表示什么,以及 L C A LCA LCA表示什么。

d e p t h depth depth: 一个节点到根节点的深度加1
也就是说,从这个节点开始往上走,一直走到根,期间经过的点的数量

L C A LCA LCA: 两个节点的最近公共祖先。
也就是说,从这两个节点中的一个往上走,对每一个经过的点打上标记;然后另外一个节点也向上走,如果遇到了一个打上标记的节点,立即将这个节点作为它们俩的LCA

综上所述, d e p t h ( L C A ( i , x ) ) depth(LCA(i,x)) depth(LCA(i,x))就等价于: 让 i i i不停地往上走,对每一个走到的节点打上标记,即将该点的点权加 1 1 1;然后再让 x x x往上走,标记的总数量(即点权之和)就是 d e p t h ( i , x ) depth(i,x) depth(i,x)

于是, ∑ i = l r d e p t h ( L C A ( i , x ) ) \sum_{i=l}^r depth(LCA(i,x)) i=lrdepth(LCA(i,x))也可以通过类似上述方法来求出。


首先,本题的询问似乎很难处理,而且询问也没有强制在线,于是我们考虑离线。同时,我们再将一个询问拆成两个询问,即查询 [ 1 , r ] [1,r] [1,r] [ 1 , l − 1 ] [1,l-1] [1,l1],二者相减即可。

然后,我们对于现在的 2 m 2m 2m个询问从小到大排序。每次加入一个新节点,就将它到根节点的路径上所有节点的点权都加 1 1 1;对于每一次询问,查询它到根节点路径上每个节点的点权之和。这相当于“路径修改,路径查询”,可以通过重链剖分套线段树在 O ( q log ⁡ 2 n ) O(q \log^2 n) O(qlog2n)的代价下搞定。

总时间复杂度 O ( n + q log ⁡ 2 n ) O(n+q \log^2 n) O(n+qlog2n)。注意取模即可。

Summary

有时,区间查询可以转化为更容易处理的前缀查询,方便我们“莫队”离线处理。同时,本题也考察了树链剖分,是一道不可多得的LNOI好题。

例3. [GXOI/GZOI2019]旧词(改编)

Description

给定一棵包含 n n n个节点的树和一个常数 k ( 1 ≤ k ≤ 1 0 9 ) k(1≤k≤10^9) k(1k109) q q q次询问,每次给定 l , r , x l,r,x l,r,x,请你求出 ∑ i = l r d e p t h ( L C A ( i , x ) ) k \sum_{i=l}^r depth(LCA(i,x))^k i=lrdepth(LCA(i,x))k

这里的 d e p t h depth depth表示一个节点的深度,即其与根节点的距离 1 1 1

由于答案可能很大,请将其对 998244353 998244353 998244353取模。

Solution

我们仍然将每一个询问拆成两个,离线下来排序。但是 k ≠ 1 k≠1 k=1似乎很难办……而且 k k k这么大,二项式定理拆开都不行……

别慌,我们考虑能不能通过一步差分,将本题转化为例2。定义 A i = ( d e p t h i + 1 ) k − d e p t h i k A_i=(depth_{i}+1)^k-depth_{i}^k Ai=(depthi+1)kdepthik,对于新加入的一个节点,从它到根节点的路径上每个节点都加上一个 A i A_i Ai;对于一次查询,仍然查询它到根节点的路径上所有节点的点权之和。我们可以处理出 A A A的前缀和,然后通过树剖套线段树求出。

这种做法为什么是正确的呢?根据差分的性质,从一个节点到根节点的路径上求出点权之和,就是这个节点本身的贡献之一。于是,每次查询我们都能得到正确的答案。

总时间复杂度仍然为 O ( n + q log ⁡ 2 n ) O(n+q \log^2 n) O(n+qlog2n)

一些练习题

①P6070
先挖一个比较显然的性质,然后直接二分差分即可。

②[ABC155F]Perils in Parallel
一道套路题,通过差分可以转化为单点修改,然后建图乱搞即可。

③P3620
一道经典题,通过差分进行等效转化即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值