【题解】P6717 线段树 分治 序列分块

$O((n+q)\log n)$ 做法,还能支持区间查,感觉很典但是别的题解没有提到。

有套路: 如果你做过 它的加强版 , 强烈推荐这个题,真的很有意思。

前置知识:线段树维护 $a_x +b_y\ (x\leq y)$ 的最最大值: 维护去加 $a,b,a_x +b_y\ (x\leq y)$ 的最值,不难发现信息可以合并,只用考虑左儿子的 $a $ 配右儿子的 $b$。

为方便称述令 $k\gets k-1$, 两个数的下标差不超过 $k$。

套路:选择两个距离至少为 $k$ 的数可以把序列错开 $k$ 位然后维护 $a_x+b_y \ (x\leq y)$ 的分治结构,而选择两个距离至多为 $k$ 的数直接这样错开 $k$ 位,维护 $a_x+b_y \ (x\geq y)$ 可能会导致选择了一个后面的数而且距离大于 $k$ 而假掉。

于是我们考虑把序列割开成 $k$ 个一段那么答案一定出现在两个相邻的段之间或者一个段内。 段内随便选,选最大次大就行,随便拿数据结构维护。

两个段之间问题就比较好解决了,像刚刚上面那样再将序列错位再维护就可以了。

具体地说就是维护 $a_x+a_{y+k}\ (x\geq y)$ 的最值,带入上面那个形式用线段树维护就行了。

再拿一个数据结构维护所有段的答案,更改时只会涉及到段内和相邻的两端,直接在线段树上更改后再改下全局答案就行了,复杂度 $O((n+q)\log n)$。

要做区间查的话就再加两棵大线段树维护段的答案和两端之间的答案,有修改的话算完答案要同步更新在这两棵线段树上,然后查询就在这两棵线段树上先查一下,然后就只剩边上的答案了,边上查下两段的最大次大,然后剩下就是边段和整段之间的答案,可以通过在原来那个线段树上查两次得到,大概就是散块部分能用的部分的 $a_x+a_{y+k}\ (x\geq y)$,和散块最值加整块全都能用部分,如果 $l$ 和 $r$ 在相邻的块里的情况需要稍微分讨一下,也可以用 $O(1)$ 次查询解决,复杂度还是 $O((n+q)\log n)$。

posted @ 2023-02-01 21:27  寂静的海底  阅读(25)  评论(0编辑  收藏  举报  来源