ABC282_H

上次做这题挺有感触,本来想写点东西,奈何写了一半 Typora 卡死,写的东西都丢失了,这次又有了新的感悟,决定一起写出来。

这道题看到前面的 \(\max\) 就可以想到,可以对于每个 \(a_i\) 求出其支配区间,然后 \(a_i\) 会将支配区间分为两段,枚举短的那一段,对长的那一段进行二分即可。

这样看似复杂度会高达 \(\mathcal{O}(n^2\log n)\),实际上却是 \(\mathcal{O}(n\log^2n)\) 的优秀算法,足以通过本题。

以下我们将说明复杂度为 \(\mathcal{O}(n\log^2n)\) 的原因:

观察可以得出,支配区间实际上呈二叉树的结构,具体地说,最大值的支配区间是整个数列,然后数列被最大值分为两段,左段的最大值支配了整个左段,右段的最大值支配整个右段,那么从整段的最大值点向左右两段的最大值点连边,于是可以递归处理左右两段,建出一棵二叉树(这棵二叉树实际上是一棵笛卡尔树)。

可以观察到一个性质,某个节点对应的子树大小,和它的支配区间长度相等。

那么对于每个结点,枚举其左右儿子的支配区间中 长度较短的那一段,这个复杂度就相当于是 dsu on tree 的复杂度,是 \(\mathcal{O}(n\log n)\) 的。

那么在本题中算法的复杂度便是 \(\mathcal{O}(n\log^2 n)\)

在本题中,实现上不必建出笛卡尔树,直接单调栈求出支配区间后枚举 \(a_i\) 二分即可。

做完本题还可以去看看 CF1777F。

posted @ 2023-01-23 18:13  wiki0922  阅读(44)  评论(0编辑  收藏  举报