【专题】偏序,扫描线
【关键字】偏序,数点,树状数组,线段树,扫描线。
因为涉及多种算法,所以整合到一起。
【扫描线】
二维数点,偏序
★数点问题
扫描线是一维离线的做法的统称,常用于解决k维偏序问题。
离线:将其中一维的询问排序后按顺序处理,从而实现按时间顺序处理的过程中可以O(1)统计空间上小于某个数字的答案。
将一维离线称为扫描线,就是因为离线的那维处理过程很像一条线按顺序扫描。
偏序:以二维偏序为例,对于任意(x,y),必须满足x<=A&&y<=B,也就是有两个单向限制,则是二维偏序。
扫描线解决k维偏序问题是经典中的经典。
一维偏序:排序扫描线 树状数组
二维偏序:排序扫描线+树状数组(差分)/线段树
三维偏序:排序扫描线+cdq分治+树状数组 排序扫描线+二维数据结构
数据结构实际上就是普通的处理一维,排序(离线)后按顺序就是用扫描线特殊的处理一维,k维中只有一维能使用扫描线。
一维用扫描线后,另一维用树状数组维护前缀和(包括前面行的,每个元素都代表一列),这就是典型的二维偏序问题解法了。
扫描线就是主要用于解决k维偏序问题的,而解决矩阵数点问题完全是利用偏序问题来解决的。
矩阵可以理解为四个限制(四位偏序),但是两维和另两维之间有直接关系,所以可以差分成四个二维偏序,这样就只要在二维偏序的时候两维分别差分即可。
例题:
★经典【STSRM13】绵津见 二维偏序,排序+树状数组
【BZOJ】1537: [POI2005]Aut- The Bus 排序+线段树
BZOJ 4822: [Cqoi2017]老C的任务 等待解决=v=
嗷嗷待补:
BZOJ 4059 Cerc2012 Non-boring sequences 线段树+扫描线
矩阵面积并
【链与反链】
引用自:最长反链与最小链覆盖 by vfleaking
大前提:在DAG上(有向无环图)
链是点的集合,这个集合中任意两点单向可达。
反链是点的集合,这个集合中任意两点互相不可达。
★最小链覆盖=最长反链
最小反链覆盖=最长链
经典模型:最少严格递减子序列覆盖=最长不严格递增子序列
最少不严格递增子序列覆盖=最长严格递增子序列(链与反链的互补关系)
不严格证明:从二分n log n求LIS的过程中可以得到一组合法解。
二分求解LIS:从前往后每个数字在替换掉序列b中第一个>=它的数字(这个数字的位置就是f[i]),如果没有则加在末尾。
二分过程中一个位置当前和之间的所有数字组成一个不增子序列,位置总数就是最长上升子序列。
int k=0; for(int i=1;i<=n;i++){ int x=lower_bound(b+1,b+k+1,a[i]+1)-b; f[i]=x; if(x==k+1)b[++k]=a[i];else b[x]=a[i]; }
(顺便一提,LIS还可以写树状数组,查询值域前缀max,值域离散化——注意树状数组不能处理ai=0的情况,需整体+1)
这样替换的正确性在于:访问某位置时,其前面的位置一定存在数字在该位置之前(反证:若不存在,则一定会替换该位置),这样传递下去可以找到上升子序列。
最长上升子序列(LIS)本质上是二维偏序,要求满足a[i]<a[j]&&h[i]<h[j]的最长序列。
也可以视为二分图不交叉最大匹配(上帝选人):一维排序(a[i]),一维可以树状数组维护DP,也可以二分。
链模型转化:对于所有满足满足a[i]<a[j]&&h[i]>h[j]的点i和点j连接有向边,最长链覆盖=最长反链。
NOIP 1999 导弹拦截
★【BZOJ】1143: [CTSC2008]祭祀river
最长链:偏序转化而来,参考LIS用DP+二分/树状数组。
链覆盖:floyd传递闭包(转化为可达信息),转化为最小路径覆盖,ans=N-最大匹配(二分图)。