OI 学习总结 part3
8/15 思维题周考总结
100+100+100+100+0+0。
T5
考虑了递减就平均一下,但不全面,需要用单调栈。
T6
我考虑过吧最小的放第一个,但直觉告诉我是错的,结果我的直觉错了。
8/14 DP 状态设计
状态的常见类型
1.位置型状态
\(dp_i\) 表示前 \(i\) 个的答案。
\(dp_{i,j}\) 表示区间 \([i,j]\) 的答案。
\(dp_u\) 表示以 \(u\) 为根的子树的答案。
等等。
2.资源型状态
\(dp_{i,j}\) 表示前 \(i\) 个,用了 \(j\) 次操作的答案。
等等。
3.历史等价类状态
如果一个状态转移,需要记录很多之前的选择,那就考虑之前的一些选择是否对当前的转移等价,不记录这些选择,否则一定记录差异。在一些题目下可以降维。
4.关系型状态
记录状态之间的关系而不是状态本身。例如把具体数列转成相对顺序,
dp 设计状态常用流程
先写出暴力转移,然后看能不能优化掉哪一维。接着考虑状态转移方程,最后在考虑优化转移。
降维技巧
代数降维
直接计算出某个维度。
可行性 dp 降维
可行性 dp 只记录零或一,可以把记录的改成某一维,并且保证只需要用到记录的。如记录最大值/最小值,转移时也只需用到最大值/最小值。
排序
在二位偏序上排序消掉一维偏序。适用于一些其他的非二维偏序问题。也就是把某一维变得有单调性。
例题
abc238f
对第一维排序,正常 dp。
P1006 [NOIP 2008 提高组 ] 传纸条
首先注意到回来跟过去是等价的,把问题转成过去两次,然后四维 dp。发现第一次过去时的 \(i,j\) 和第二次过去时的 \(k,l\) 加起来相等,直接算出 \(l\),降成三维。当然直接四维是可以做的。
dp_t 变式

注意到每个 \(<\) 肯定要除以相同的数,和前面没啥关系,可以 dp。
8/13 扫描线、二位数点测试总结
T1
0.1秒看出正解,30min打完,调了30min,失败,线段树区间合并还不是很熟悉,有待加强。
T2
没想出来。观察力有待加强。
8/12 扫描线练习 2
Gym-102979C Colorful Squares
先二分答案 \(s\) 转判定性问题。考虑扫描线,对于大小为 \(s\) 的正方形,先把 \(x = x_0\) 的所有点加入集合,再在 \(x = x_0 + s + 1\) 的时候把 \(x = x_0\) 加入的点从集合中删除。那么现在就是判断集合中是否存在一个 \(y\),使得 \([y - s, y]\) 里面有所有的 \(k\) 种颜色。
设有一个数据结构,其每个点 \(i\) 维护 \([i - s, i]\) 的颜色种类数,假设我们加入点为 \(y_0\),那么它会增加该数据结构中的 \([y_0, y_0 + s]\) 中所有点维护区间的颜色种类数,该操作即区间 \(+1\),不过,可能这其中已经有些点包含了该点的颜色 \(c_0\),故而,我们还需要对于每个颜色开一个 multiset 维护该颜色所有的位置,插入 \(y_0\) 时,找到前驱和后继 \(y_1, y_2\),那么我们最终修改的区间就是
最后统计时,只需查看是否存在某个位置维护的值为 \(k\) 即可,这和区间最大值差不多。撤销操作,其实就是区间减 1。
关于数据结构的选择,显然我们可以使用线段树做到。时间复杂度 \(O(n \log x \log a)\)。
[ARC201E] Total Area of Bounding Boxes
考虑对于一个 \(a_i\),它作为 \(min_y\) 了多少次。设比 \(a_i\) 高的点的个数为 \(s\),此时次数即为 \(2^s\)。\(max\) 等同理。
8/11 扫描线练习
P9478
横线竖线就是扫描线板子,斜线直接暴力判跟每条线是否相交,然后把所有交点记录进 set 里看有多少个就行了。
ABC211F
难点在于入边出边的处理。对于每个多边形,首先找到最靠进 y 轴的边,从这条边开始,按输入顺序,一定是入边、出边、入边、出边……。此题就成了板子。
ABC360F
把 \((l_a,r_a)\) 看成一个点,题目中的条件即为:\(l_b \in[l_a+1,r_a-1]\), \(r_b \in[r_a+1,+\infty ) l_b \in[0,l_a-1] , r_b \in[l_a+1,r_a-1]\),也就是矩形加。求的就是哪个点被包含了最多次。
注意线段树要维护覆盖次数、最大覆盖次数、最大覆盖次数的最小位置。
8/10 二维数点进阶
常见二维数点
基本二维数点
二位数点基本:给定 \(n\) 个二维平面上的点和 \(m\) 条询问,每次询问一个矩形内有多少个点。
对于每个询问,把矩形 \([x_1,y_1][x_2,y_2]\) 拆成 \([0,x_1][0,y_1]-[0,x_2-1][0,y_1]-[0,x_1][0,y_2-1]+[0,x_2-1][0,y_2-1]\)。这样每一个拆出来的部分就好维护。从下往上扫,每扫到一个点加进树状数组,每扫到一个拆出来的询问就统计答案(需要离线)。
如果是区间修改单点查询,就把修改改成差分,和查询一起扫即可。
如果强制在线,把树状数组改成可持久化线段树,先扫一遍记录历史版本,对于每个询问查询对应的历史版本即可。
二维数点求最大最小值
如果二维数点求的信息不满足可见性(例如 max、min)就需要更换方法。
如果查询形如 \(x_i \le X, y_i \le Y\) ,那么直接套用问题 \(1\) 的做法。
如果只有一个维度查的前缀,使用线段树。
否则只能树套树或整体二分,遇到这种情况要么是问题转化错了,要么是题太难了。
动态二维数点
加入时间轴,使用线段树分治或 CDQ 分治解决。
矩阵加,矩阵查,强制在线
注意这里是先全部加完再强制在线查。
其实就是二维树状数组区间查区间修的思想,但是空间开不下,所以要用到二维主席树(动态开点)。
例题:bzoj 2874
拓展:二维数点,但不一定是矩形
练习题
ABC233Ex
第 \(k\) 大/小经典套路:二分答案
二分答案曼哈顿距离,如果距离 \(x,y\) 小于当前的 \(mid\) 的个数 \(<k\),就扩大,否则缩小。
但是我们发现,距离 \(x,y\) 固定曼哈顿距离的矩形是斜 \(45\) 度的,无法直接二维数点。这需要一个trick,把每个点 \((x_i,y_i)\) 改成 \((x_i+y_i,x_i-y_i)\),此时整个点集就旋转了 \(45\) 度,然后就可以二维数点。
洛谷 P10281
首先推出什么情况下满足题目条件。推出来是 \(l_j<=r_i-k_i\) 且 \(rj>=k_i+l_i\) 且 \(r_j-l_j>=k_i\)。
此时无脑 CDQ 可以解决,但是有更优的二维数点做法。
对 \(min(r_i,r_j)>=ki+max(l_i,l_j)\) 分类讨论。
情况 1 : \(r_j\ge r_i,l_j\le r_i-k_i\)
情况 2 : \(r_j\ge l_i+k_i,r_j<r_i,r_j-l_j\ge k_i\)
分别维护两个二维偏序即可。
洛谷 P13094
这种区间求满足条件的有一个套路:预处理出每个元素能作用到的最远的左右端点。
如果预处理出每个点往左往右最长可以拓展到的位置 \(l——i,r_i\) ,即在
[l_i,r_i] 内没有点两个维度都 >= 自己,问题就被转化成了矩形 \([l_i,i][i,r_i]+1\),查询 \((L,R)\) 单点。
预处理部分,先看 \(l_i\)。需满足 \(x_j\ge x_i,y_j\ge y_i,j<i\),并且 \(j\) 最大。直接三维偏序是双 \(\log\),但是我们其实只用求最大的 \(j\),所以把 \(y_i\)插入线段树 \(i\) 的位置,线段树维护区间 \(max\) ,线段树上二分就可以找到 \(j<i\) 且 \(y_j\ge y_i\) 的最大的 \(j\) 了。时间降了个 \(log\)。

浙公网安备 33010602011771号