算法学习笔记(44): 二维问题小计
首先需要理解什么是二维问题。
二维问题就是每一个元素都可以看作一个平面上的坐标 。其中一维可以是下标,时间,值,dfn
,甚至是一个函数 。
经典的二维问题实际上就是矩形加,矩形取 ,单点查,线查,矩形查。
而二维问题一般是通过某种建模方式变成上述操作进行操作。
- 区间一次问题
例如给定序列,多次询问一个区间是否有重复的数。
虽然这原本是一个一维问题,但是可以升维更简单的处理。
- 解法 :经典方法,令 表示 前面第一个与它相同的位置,那么一个区间没有重复的数当且仅当 ,于是升维之后变成了一个简单的区间 问题。
- 解法 :将每一种数单独处理,设 表示值为 的第 个数的位置,那么一个区间 如果只被 覆盖了一次,那么需要满足 ,。将询问看作二维平面上的一个点,那么被贡献到的矩形有 个,而一个区间全部都只出现了一次,那么它一定被贡献的区间长度次,于是问题转化为矩形加,单点查的问题,只是需要离线,并且常数略大。
- 解法 :类同解法 ,只是考虑被 覆盖了不止一次的区间,那么需要满足 ,,这样的矩形也是 个的。
- ……或许还有更多的想法
对于解法 可以看作一个很好的套路,被玩烂了,但是解法 就非常有意思。
我们首先将每一个点对于区间的贡献拆了出来,也就是拆贡献。将自由度为二的问题看作了平面上的点,拆除的贡献是一个矩形贡献,那么就可以变成经典的二维问题了。
例:BZOJ#3489. A simple rmq problem 在 之间找到最大的在这个区间里只出现过一次的数。
这用 解法 其实也可做,但是如果需要判断一个数是否只是出现了一次,那么不仅需要前驱 ,还需要后继 ,当 , 并且 的时候才可以对答案做出贡献,这是一个三维偏序问题,利用 cdq
分治可以做到 的复杂度。
利用 解法 来做无论是代码还是思路都将十分的简单,因为我们只需要将提及的矩形加贡献变为矩形取 贡献即可,利用扫描线与 set
可以做到 的复杂度,注意到这个是可以转化为可持久化线段树支持在线的。
- 换维扫描线
将动态的一维问题转化为静态的二维问题,实际上就是增加了时间这一维度。
这里的换维扫描线实际上就是将对于时间维的扫描线(动态的一维问题)转化为对于序列的扫描线(另一个动态的一维问题)
例如维护一个序列,支持:
- 区间
- 单点求历史最值
这道题实际上可以利用历史版本最值线段树完成……但是这里不是讲这个的。
历史版本最值线段树可以参考:# 算法学习笔记(34): 矩阵乘法与线段树标记。
如果我不会这个神秘的科技怎么办?如果以序列为横坐标,时间为纵坐标:
那么区间修改形如红线,而查询最值形如蓝线
上下略微有些颠倒,不过问题不大。
如果我们竖着来扫描线,那么修改就变成了单点修改,而蓝线也就是前缀查询。
而历史最值呢?实际上也就是一个前缀最值问题,这是容易维护的。
- 例题:UR #19 前进四 维护一个序列 ,单点修改,查询某个后缀后缀最小值的个数。
首先对于每次询问暴力做是简单的,注意到我们只需要维护两个变量: 表示后缀最小值和变化的次数。
每次 ,如果 改变了,那么 。
我们对于其多加一个下标 ,那么 。
注意到 在 固定的时候有若干连续段的值是相等的,这样的段是 的,考虑同统一进行上述转移,其实也就是换维扫描线,那么问题转化为维护一个序列:
- 区间取
- 单点查询一个点被取 变小的次数
这是 seg beats
需要完成的事,不在本文讨论范畴内。
还有一些利用这个方法完成的题:
我们说了序列上的二维问题,对于树上的二维问题又是什么呢?
- 树上二维问题
一般来说,我们需要利用 dfn
序的映射,因为它具有很好的性质。
- 例:定义一个点对 是好的当且仅当:。给定一棵 个点的树,树上点的权值互不相同,每次询问给定一个路径 ,问路径上多少个点对 满足 且 是好的。。
对于每一个 可以 预处理出可以与那些点形成贡献,考虑这些点对会对那些路径造成贡献。
- 点对非祖孙关系,那么如果路径两个端点分别在点对的子树内,那么可以被贡献。
- 点对为祖孙关系,若 是浅的那个,那么一个端点 或者 ,另一个端点 且 。
发现将左右端点看作二维平面上的点,那么一个点对会导致 个矩形加法,于是扫描线即可,可持久化之后可以强制在线。
- 例:用 个节点建出了了两棵有根树,询问两棵树某两个子树内的节点是否有交。
同一个节点在两个树上的 dfn
是不同的,所以自然是一个二维的元素。
由于子树内的 dfn
是一段连续的区间,那么问题转化为判定一个矩形内是否存在一个点,那么也就是经典的二维数点问题,随便做啦。
这个问题实际上是 [IOI2018] werewolf 狼人 的后半部分,前一半部分是 kruskal 重构树,可见:# 算法学习笔记(30):Kruskal 重构树
一道强化的问题,带修:Intersection of Permutations。
所以讲来讲去,二维问题到底是怎样的一个问题,有没有什么通法来解决呢?个人理解,仅供参考
二维问题,大部分情况下是表面上的一维问题。但是一维能够维护的信息太少太少了,所以需要更多的信息,例如时间,数值来增加可以维护的信息量,从而更好的解决问题。
而通法……我太菜了,没有通法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?