【BZOJ 4127】Abs(树链剖分,线段树)

该博客介绍了如何使用树链剖分和线段树来解决一个图论问题,其中涉及对树上的路径进行加权操作和查询路径上点权重绝对值的和。博主详细讲解了思路,包括如何维护区间正数和、最大负数等信息,并讨论了处理懒标记和区间更新的策略。最后,博主提到了代码实现中的关键细节和时间复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

题目传送门

Description

给定一棵树,设计数据结构支持以下操作
1    u    v    d 1 \;u\;v\;d 1uvd 表示将路径 ( u , v ) (u,v) (u,v) d d d
2    u    v 2\;u\;v 2uv 表示询问路径 ( u , v ) (u,v) (u,v) 上点权绝对值的和

Input

第一行两个整数 n n n m m m,表示结点个数和操作数
接下来一行 n n n 个整数 a i a_i ai,表示点 i i i 的权值

接下来 n − 1 n-1 n1 行,每行两个整数 u , v u,v u,v 表示存在一条 ( u , v ) (u,v) (u,v) 的边

接下来 m m m 行,每行一个操作,输入格式见题目描述

Output

对于每个询问输出答案

Sample Input

4 4
-4 1 5 -2
1 2
2 3
3 4
2 1 3
1 1 4 3
2 1 3
2 3 4

Sample Output

10
13
9

Hint

对于 100 % 100\% 100% 的数据, n , m < = 1 0 5 n,m <= 10^5 n,m<=105 0 < = d , ∣ a i ∣ < = 1 0 8 0<= d,|a_i|<= 10^8 0<=d,ai<=108

思路

树链剖分+线段树,考虑如何维护这棵线段树。
由于这题是绝对值和,维护 lazytag 时,正负性不容易处理,考虑往区间和上靠。
注意到:区间绝对值之和 = = = 2 × 2 \times 2×区间正数和 − - 区间和,所以本题转化成了维护区间正数和。
在线段树中,需要再维护几个东西:

  1. maxf:区间最大的负数
  2. sum:区间正数和
  3. num:区间正数的个数
  4. tag:sum 的懒标记
  5. tagg:maxf 的懒标记(一开始大e了,没有闪,忘了 maxf 也是要下传懒标记的了)

修改时,注意到每一次增加的量 d ≥ 0 d \geq 0 d0,所以每一个数只会被从负数变成正数一次,那么这样的操作最多总共只会出现 n n n 次,对于这些操作,我们就将线段树递归到底,暴力修改。

而对于其余的操作,我们只需正常的区间修改即可。

如何判断一次操作后,区间内有负数变成正数呢?这就用到了 maxf,如果 m a x f + d > 0 maxf+d>0 maxf+d>0,就说明有数从负变正,否则没有。

正数区间我们就将 maxf=-inf,这样 也许? 可以避免一些麻烦?(还是要很多特判,我也因此晕蛋了,对拍了 2h)

细节比较多,考虑清楚,注意好懒标记的下传,注意好 sum 和 num 的维护,记得即使是 m a x f + d < 0 maxf+d<0 maxf+d<0 的操作中,可能是有正数也有负数的区间,依旧要维护 sum。

时间复杂度:对于由负变正的操作,单次操作 O ( l o g    n ) O(log\;n) O(logn),总操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值