区间操作杂谈
本文从易到难 (大概) 介绍了一些区间上的经典操作
1.一些线段树水题
查询可合并信息、单点修改/区间修改、区间查询
其中的“可合并信息”可以是 加法、乘法、位运算 及其组合。
前者为线段树板子,不再赘述。
水经验:
区间加,区间查询:P3372 【模板】线段树 1
区间加、乘,区间查询:P3373 【模板】线段树 2
区间修改、区间加、区间求
重点在于后者,这里给出 (瞎编) 了几道题:
1.
维护长度为 n 的序列,支持区间加,询问区间方差。
方差的定义:
其中
稍微化一下式子:
于是只需维护 区间和 以及 区间平方和 即可。
考虑怎么维护 区间加:
对于 区间和,直接加上即可;
对于 区间平方和,每一项由
那么一次 区间加 对 区间平方和 的影响为
于是每次 区间加 的时候对 区间平方和 加上这部分即可。
题目:
P5142 区间方差
P1471 方差
P2122 还教室
2.
维护长度为 n 的序列,支持区间加,询问区间内所有有序数对两数乘积之和。
其实就是求
的值。
交换下求和顺序:
首先觉得这个式子不顺眼,将其乘二:
觉得
也就是:
于是题目就是求:
于是维护下 区间和 以及 区间平方和 就行了。
3.
P4513 小白逛公园
维护长度为 n 的序列,支持单点修改,查询区间内最大子段和。
经典题。
“最大子段和”显然不是一个可合并信息。
于是考虑将其拆分成几个可合并信息。
大力分类讨论:当前区间的最大子段和 越过/未越过 两个子区间分界线。
如果未越过分界线,取两个子区间的 最大子段和 即可;
如果越过分界线,将这个最大子段从分界线处分开,拆分成 左子区间的右起最大子段和 + 右区间的左起最大子段和。
如果能维护出右起最大子段和和左起最大子段和,就能计算出两种情况的最大子段和,当前区间的最大子段和就分别它们取
接下来只需考虑区间内右起最大子段和和左起最大子段和怎么维护。
再大力分类讨论:当前区间的右起最大子段和越过/未越过 两个子区间分界线。
如果未越过分界线,取右区间右起最大子段和;
如果越过分界线,取左区间右起最大子段和+右区间区间和。
左起最大子段和同理。
于是一个区间需要维护
4.
P3792 由乃与大母神原型和偶像崇拜
单点修改,查询区间 [l,r] 是否可以重排为值域上连续的一段
判断问题是比查询问题要简单的,于是考虑乱搞做法:
显然的,如果
首先判断这个重排序列的长度,其次判断这个序列的一个与顺序无关的特征。
可以取区间和以及区间平方和,当然也可以取区间异或和之类的乱搞判断,本质就是一种与顺序无关的哈希。
区间平方和判断时注意值域溢出。
5.
P2056 [ZJOI2007] 捉迷藏
给出一棵 N 个有色(黑白,黑色对应关灯,白色对应开灯)节点的树以及 M 次操作,
每次操作将改变一个节点的颜色或者求出树上最远的两个黑点距离
实际上就是求所有黑点构成树的直径。
对编号为
考虑如何合并信息:设左区间为
于是线段树上维护 [l,r] 这些点组成的树的直径长度,直径两端点,然后暴力合并即可。
单点修实现显然。
后记:实际上这题正解是淀粉树,但我不会。
类似的题但我不会写(动态维护直径满血版):P6845 [CEOI2019] Dynamic Diameter
一些题:
如题:P6327 区间加区间 sin 和
区间加等差数列,单点查询:P1438 无聊的数列
挺有意思的题:P4588 [TJOI2018] 数学计算
同上:P8862 「KDOI-03」还原数据
2. 一些杂题
P1972 [SDOI2009] HH的项链
给定一序列 a,每次询问区间内数字种类数。
经典题。
一个经典而巧妙的 trick:对第
询问一段区间内数字种类数,等价于一段区间内第一次出现的数的个数(废话)。
因次我们无需关心重复出现的数的个数,只需关心第一次出现的数的个数。
而如果一个数
那么 区间数的个数 = 区间第一次出现的数的个数 = 区间内
用主席树简单维护下就没了。
双倍经验
P2048 [NOI2010] 超级钢琴
求区间内长度在 [L,R] 内的前 k 大子段和 的总和。
先考虑怎么维护区间最大子段和:
直接正面硬刚不怎么好做,考虑维护一个前缀和。
对于一个子段
由于
然后考虑怎么维护前
对于每一个左端点,维护一个三元组
先枚举左端点把初始的三元组
每次取出当前最大子段和对应的三元组
插入与弹出的数个数是
当然也可以用
口胡另外一个做法:对每个左端点
未完待续...