Yet Another Range Query Problem
题解
首先,看到这道题,我们应该是比较容易联想到扫描线加线段树的。
我们考虑维护每个点作为左端点到当前扫到的这个点作为右端点之间区间的信息。
显然,我们每次多在末尾加入一个数,只会改变一段连续区间的最小值与一段连续区间的最大值。
这个显然可以用栈维护,找到它会改变的是哪一段,显然,如果一个数能覆盖上一个数,那他肯定是能覆盖上一个数覆盖的所有数的。所以这部分是 O ( n ) O\left(n\right) O(n)的。
那我们考虑我们该怎么计算答案呢?
显然我们不大可能在每一层都询问一下包含这一层的所有询问,这不 T T T麻才怪。
这也就是说我们必须通过差分求出我们的答案。
如果要差分的话也就是说我们得记录历史和,不过貌似这个历史和不太好通过懒标记进行区间更改,但它应该是可以的。
其实大部分这样的懒标记更改,最后统计和的,我们都可以考虑通过矩阵来实现。
我们假设每个点上就记录向量 ( ∑ min , ∑ max , ∑ min ⋅ max , history sum , s i z e ) (\sum \min,\sum \max,\sum \min \cdot \max,\text {history sum},size) (∑min,∑max,∑min⋅max,history sum,size)。
那么显然,我们的操作都可以表示成对这个向量乘上一个矩阵。
比如说我们更改最小值就会使得 ∑ min \sum\min ∑min和 ∑ min ⋅ max \sum \min\cdot\max ∑min⋅max发生更改。
由于都是改成一个相同的值,也就是 ∑ min \sum\min ∑min变成 x ⋅ s i z e x\cdot size x⋅size, ∑ min ⋅ max \sum \min\cdot\max ∑min⋅max变成 x ∑ max x\sum\max x∑max。
说成矩阵就是,
[ 0 0 0 0 0 0 1 x 0 0 0 0 0 0 0 0 0 0 1 0 x 0 0 0 1 ] \left[\begin{array}{cc} 0&0&0&0&0\\ 0&1&x&0&0\\ 0&0&0&0&0\\ 0&0&0&1&0\\ x&0&0&0&1 \end{array}\right ] ⎣⎢⎢⎢⎢⎡0000x010000x0000001000001⎦⎥⎥⎥