LXL DS tricks
单侧递归系列
区间函数复合
每个节点是一个函数,区间询问给定值通过 这些函数值变成什么。
两种思路,直接维护和标记回收,都是没有修改的情况。
直接维护就是维护一棵线段树,每个节点的信息量是区间长度。
标记回收则比较牛,对于若干询问进行扫描线,扫到 的时候把询问的 扔进数据结构,扫到 的时候掏出来,每次右移的时候就把所有节点进行一个操作。
如果函数只有 个变化的点,我们可以直接并查集把所有变化并上,再新建点给失去了根的值。
P9999 [Ynoi2000] tmostnrq & 2d-travel
修改对询问的反演
常见的,前缀加单点查变成单点加前缀和,树上差分。
UOJ 637. [美团杯2021] A. 数据结构
给一个长为 的序列, 次查询:
如果将区间 中所有数都 ,那么整个序列有多少个不同的数?
询问间独立,也就是说每次查询后这个修改都会被撤销。
考虑修改对查询的贡献,也就是我们要维护 的答案平面。
一个数不出现当且仅当 ,且 。
不出现的贡献是一个矩形。
扫描线换维
说的很轻松,实际上不练过很难反应过来。
P3863 序列
给定一个长度为 的序列,给出 个操作,形如:
表示将序列下标介于 的元素加上 (请注意, 可能为负)
表示查询 在过去的多少秒时间内不小于 (不包括这一秒,细节请参照样例)
开始时为第 秒,第 个操作发生在第 秒。
对于 的数据,保证 , , ,。
扫序列,维护时间轴,变成区间加区间 rnk,分块即可。
有一类特殊的换维,当我们遇到一个正常区间数据结构问题的时候,别忘了还有 这一维,扫区间维护时间轴有时更好用。
P7560 [JOISC 2021 Day1] フードコート
有 个队列。
- 入队 次 。
- 出队 次,出完了就停。
- 求第 个队列的第 个人,没有这个人需要报告。
。
有一个初步的思路是如果没有“出完了就停”,我们可以直接扔掉 操作,转而改一改 操作的 。
扔掉之后我们可以用整体二分来求出哪个操作导致了这个询问的警报。
或者再松一松,“没有这个人”的情况也不存在,那再加上没有出队,我们可以把询问移到最后处理,所以我们可以直接线段树维护区间 ,然后直接警报。
那么如何保证没有这两种讨厌的情况呢,我们可以转而维护 时刻的每个队列的长度,这样我们首先可以判掉“没有这个人”,然后也可以利用 入队了多少次 来求出扔掉 操作后询问的偏移量。
维护长度只需支持区间加,区间对 取 ,这个东西是单 的。
需要注意,如果仅仅是区间取 ,区间取 ,区间求 ,区间求 ,区间加,这是可以单 的,只有求区间和这种阴间东西的时候才需要 beats,带上区间加就 。
本题当然也可以换维,维护时间轴,需要支持单点修改,我们还需要找到最后一个队列为空的时刻,事实上就是后缀最大值。
显然这个时刻是空,因为如果此时非空前面还有一个空时刻,那么加上中间这段正数必定优,且后面不会是空,否则可以抛弃一段非正。
求出这个时刻后只需求出 pop 的总数,在 push 上线段树二分即可。