线段树相关杂题

[LG5490] 扫描线

扫描线模板题从小到大枚举横线的纵坐标枚举到矩形下界就给这条边的左右端点构成的区间 $+1$否则 $-1$用线段树维护当前线段树有值的结点个数就是这个纵坐标的贡献

怎么维护线段树中不为 $0$ 的位置数量呢我们发现在做扫描线的时候权值不会小于 $0$于是我们考虑维护区间最小值和最小值的数量这个在合并的时候如果左右儿子的最小值相同则将其最小值数量加起来否则继承最小值更小的那个的最小值数量

当然本题还需要动态开点所以需要维护区间内有效点的数量

时间复杂度 $\Theta(n\log n)$

[SPOJ] GSS-I

先求出前缀和发现答案为区间最大值减最小值但需要满足最小值在最大值右边

对线段树的每个节点维护最小值最大值和答案发现答案可以从两棵子树的答案更新也可以更新为右子树中的最大值减去左子树中的最小值

于是直接用线段树即可维护时间复杂度 $\Theta(n\log n)$

[SPOJ] GSS-III

发现这题是带修版的 $\rm GSS1$但是由于前缀和无法动态修改于是考虑直接维护区间和

显然要维护区间和以及最大子段和发现最大子段和需要通过左儿子的最大后缀和和右儿子的最大前缀和更新于是再记最大前后缀和而最大前后缀和是可以通过区间和和子节点的最大前后缀和计算的于是这题就可以用线段树做了

时间复杂度 $\Theta(n\log n)$

[SPOJ] GSS-IV

我们发现一个区间内如果全都是 $1$$0$那么对它开方是没有意义的所以记录最大值如果最大值为 $0$$1$那么直接跳过这个区间

我们发现这样做每个点最多被修改 $7$故时间复杂度 $\Theta(n\log n)$

[SPOJ] GSS-V

我们发现这个问题和 $\rm GSS-I$ 很像唯一的区别是左右两边限定了区间我们发现如果两个区间不重合那就是右区间最大值减左区间最小值

若两区间重合令从左到右三个区域分别为 $\rm I,II,III$首先用 $\rm \max\{II\cup III\}-\min\{I\}$ 更新答案然后用 $\rm \max\{III\}-\min\{I\cup II\}$ 更新答案最后只剩下两个端点都在 $\rm II$ 内的答案这个就是 $\rm GSS-I$

时间复杂度 $\Theta(n\log n)$

[LG4198] 楼房重建

首先肯定将每个楼房的信息转化为斜率显然要维护区间最大值和从这个区间左端点开始能看到多少栋楼

现在考虑将左右区间合并显然要先将左区间的答案加上然后考虑右区间能看到多少个点

  • 如果左区间的最大值小于右区间的左区间的最大值那么肯定对右区间的右区间没有影响将右区间的右区间的答案加上左区间递归
  • 如果左区间的最大值大于右区间的左区间的最大值那么右区间的左区间肯定一个都看不到直接将右区间的右区间递归下去

单次合并时间复杂度 $\Theta(n\log n)$总时间复杂度 $\Theta(n\log ^2n)$

$\quad\rm PS:$ 这题有个坑点计算右区间的右儿子的答案的时候不能写成 ans[RS]而是要写成 ans[p] - ans[LS]因为右儿子的答案可能会被左儿子挡掉一些这些还是不能算进去

[LG1502] 窗口的星星

考虑将每颗行星变成一个带权矩形我们发现最大亮度和就是最大矩形交的权值之和

考虑用扫描线维护区间最大值即可

坑点 $1:$ 由于边界上的点不用算所以矩形右上角为 $(x+w-1,y+h-1).$

坑点 $2:$ 我们在每次修改过后都统计了一遍答案所以当线段纵坐标相同的时候删除要排在前面防止统计了一个不合法的大的答案

[CF240F] TorCoder

考虑一次操作干了什么事情若存在一个以上字母出现了奇数次则无法重排否则将出现奇数次的字母放在最中间然后将所有字母按照从小到大再从大到小的顺序放在这个字母的两边

于是可以对每个字母开一颗线段树维护区间赋值操作和区间求数量操作即可

时间复杂度 $\Theta(n\log n|\Sigma|)$

[CF242E] XOR on Segment

考虑对每一位开一颗线段树问题就变成了维护一个 $0/1$ 序列支持区间取反和区间求和

时间复杂度 $\Theta(n\log^2n)$

[CF414C] Mashmokh and Reverse Operation

我们发现这个题目中区间的结构很像一颗线段树于是考虑它的性质

发现交换一个翻转一个区间等价于将它的两个子区间交换然后递归操作而一个区间的逆序对数量为两个子区间之间的逆序对数量加上两个子区间内部的逆序对数量

于是考虑维护每一层每一个结点的两个子区间之间的逆序对数量之和这样修改操作就变成了将某一层下面的所有区间翻转由于层数只有 $20$所以直接维护每一层是否被翻转即可求当前的答案只需要预处理每一层的所有节点的两个子区间之间的答案之和即可发现一层区间一定是一起翻转于是每一层只有两种状态分别预处理即可

时间复杂度 $\Theta[(2^n+m)n]$

[CF446C] DZY Loves Fibonacci Numbers

我们知道 $F_{n}=\frac{\sqrt{5}}{5}\left[\left(\frac{1+\sqrt{5}}{2}\right)^{n}-\left(\frac{1-\sqrt{5}}{2}\right)^{n}\right].$

于是可以发现只需要分别维护两个序列在一个序列中公比相同

故我们只需要维护首项后面的数可以直接算出来下传的时候给左子区间直接加上这个首项右子区间加首项乘上 $q^{\frac{r-l+1}{2}}$ 即可

时间复杂度 $\Theta(n\log n)$

[CF522D] Closest Equals

我们发现如果记 $p_i$ 表示距离 $i$ 最近的在 $i$ 之前的与 $i$ 颜色相同的点与 $i$ 的距离那么对于一个询问 $[l,r]$其答案为所有满足 $i-p_i\geqslant l$$i\leqslant r$ 的点中$p_i$ 最小的那个

于是考虑将坐标离散化然后将询问离线下来按右端点排序一个个枚举 $i$$p_i\not =0$则将 $C_{i-p_i}$ 的值与 $p_i$$\min$可以发现$C$ 中区间 $[l,r]$ 内的最小值就是这个区间的答案

单点修改区间查询可以使用线段树维护可以发现 $[l,r]$ 的答案和 $[l,n]$ 的答案是相同的于是也可以使用树状数组维护后缀和

时间复杂度 $\Theta(n\log n)$