扫描线

是很强大的东西。

难点是精确地刻画出限制。就是要找到限制的一个充要条件,然后放到二维平面上去用扫描线+DS维护。

常见构造二维平面的方式:以询问\([l,r]\)作为\((l,r)\);以需要维护的信息\(f_{i,j}\)作为\((i,j)\) etc.

正难则反

正着刻画限制不太行,就尝试刻画出不符合限制的情况,这样放到二维平面上。最后的答案形式或许是矩形的补。

这是常见+Simple的。

反演的想法

For instance,我们查\([l,r]\)中的颜色数,先正难则反,考虑哪些颜色在\([l,r]\)中没有出现。然后就可以先只关注一种颜色,然后\([l,r]\)在相邻的两个位置之间的询问就没有这种颜色造成的贡献。这样的\([l,r]\)放到平面上就是一个矩形,然后扫描线就好。

这样我们可以考虑一个元素对于询问的贡献然后扫描线。

来点例题

P1502 窗口的星星

link

由于窗户大小固定,我们以它的右上角来表示它的位置。考虑一个位置上的星星可以对哪些位置上的窗户造成贡献,发现贡献范围是一个矩形。

问题转化为:矩形加,查询所有点中的最值。于是扫描线可以做了。

区间子区间问题

首先需要刻画出子区间要满足的限制,剩下的都是套路。

\(f_{i,j}\)表示子区间的信息,然后就考虑每个位置作为\(r\)新造成的贡献。于是\(f\)的整个平面都可以维护出来,同时使用历史和线段树维护一个前缀矩形的满足条件的信息(子区间)的个数/或者统计贡献之类的,询问一个区间\([L,R]\)的子区间其实就是给子区间的左右端点加上了限制,\(L\le l\le r\le R\),放到平面上还是矩形,于是用前缀矩形将这个差分出来就好。

来点例题

P3246 [HNOI2016] 序列

link

\(f_{l,r}\)表示区间\([l,r]\)的最小值,那么要求的就是\(l\ge ql\land r\le qr\)的所有\(f_{l,r}\)之和。将\(l\)作为横轴,\(r\)作为纵轴构造二维平面,于是所求的就是右下方一个矩形和。(\(l>r\)的部分,我们认为\(f_{l,r}=0\))。

如何求出每个\(f\)?只需单调栈维护一个值能够贡献的区间的左右端点。放到平面上,我们只需维护矩形加,2-side矩形和。后者可以历史和线段树。

扫Sequence维,DS时间维

特点是区间修改,单点询问。

我们每个时刻在序列上做修改或查询,可以构造以序列为横轴,时间为纵轴的二维平面。发现一次修改造成的影响范围在平面上是一个矩形。

我们用DS维护时间维,维护的是操作造成的影响。扫描线去扫序列,依次回答单点询问。

来点例题

P3863 序列

link

就是矩形加,然后在扫描线上查询一段前缀中不小于 \(x\) 的数有多少个。分块维护扫描线即可。

每个询问的 \(x\) 需要结合序列上对应的值 \(a_i\) 算出来。注意一下 \(t=0\) 即初始时刻的特判。

假-斜线扫描线

看似平面上的限制又有正着的矩形又有斜着的半平面,但是实际上可以尝试拆开。

把正着和斜着的分别贡献到答案上。

正的就不动,正常做。斜着的考虑“旋转坐标系”,其实是放到另一个平面上,更改 X 轴和 Y 轴的定义即可。

可能在两个平面上扫描线扫的东西不同,视具体限制而定。

posted @ 2025-02-15 20:04  RandomShuffle  阅读(16)  评论(0)    收藏  举报