一键挖矿
如果做了这道题,有可能做出ioi2018 排座位
在一维时,问题就是询问\(\max(l...r)-\min(l...r)=r-l\)的段数。
这是个经典的问题。
从\(1\to n\)进行扫描线。设当前扫到\(i\)维护两个单调递减/递增栈和两个线段树。
第一个线段树的\(j\)位置表示\(\max(j...i)-i+j\)的值。
第二个线段树的\(j\)位置表示\(\min(j...i)-i+j\)的值。
在更新单调栈的时候可以同时更新两个线段树。
查询以当前点为结尾的段数就是查询全局最小值/最小值的个数,可以用线段树简单维护。
或者点-边就可以。
但是二维就不能这么做。
引理:如果把权值为\([l,r]\)的点全部染黑,考虑每个\(2*2\)的矩形。
当恰好有\(4\)个黑点个数\(=1\)的矩形且没有黑点个数为\(3\)的矩形时符合题目的条件,否则不符合。
必要性显然。
充分性可以考虑:
不是连通块的情况,显然角的个数会\(>4\)。
一个角可以贡献至少\(1\)个黑点个数\(=1\)的\(2*2\)矩形。
是连通块的情况,这个连通块不能有向内凹的部分,否则会出现黑点个数为\(3\)的矩形。
画图/感性理解发现这样子是正确的。
(以上纯口胡)
当得到这个结论后,我们可以在扫到\(r\)时用线段树维护\(l\)位置\([l,r]\)黑点个数\(=1\)的矩形+黑点个数为\(3\)的矩形的个数和。
这是因为黑点个数\(=1\)的矩形至少有4个。当最小值\(=4\)时,后面一项肯定为\(0\)。
在修改时区间+即可。
时间复杂度\(O(nm\log_2nm)\)