Luogu8330 解题报告

有一个显然的贪心,选了一个区间 [l,r] ,贡献为这个区间的众数加上区间外的众数。

考虑根号分治,阈值为 B 。我们称出现次数 >B 的数称为大数,反之成为小数。答案有需要分 4 类讨论: [l,r] 内是大数/小数,区间外是大数/小数

比较简单的是 [l,r] 内是大数/小数,区间外是大数。

我们发现大数的种类只有 nB 个,所以我们预处理出 sumi,j 表示前缀 i 数字 j 出现了多少次?这个部分容易做到 O(nn)

接下来我们枚举一种颜色,然后对于这个元素从左到右数的第 i 个出现位置假设我们的区间 [l,r] 以其为右端点,那么对于一个左端点 j (这个元素第 j 个出现的位置)产生的贡献就是 (ij+1)+(sumn,wsumi,w)+sumj1,w

推推柿子:

maxj<i(ij+1)+(sumn,wsumi,w)+sumj1,w

(isumi,w+sumn,w+1)(minj<isumj1,wj)

后面的 min 可以预处理啊,所以这部分可以做 O(n2B)

十分困难的是 [l,r] 内是小数,区间外是小数。

因为区间内是小数,所以这样的区间只有 O(nB) 个,考虑 O(1) 求区间外的小数,优势在于小数的数量 B

记录 fi,j 表示左端点 i 要是需要出现 j 个元素,最靠右的右端点是多少?这个东西比较容易预处理,时间 O(nB) 。那么我们对于枚举的一个区间 [l,r] ,我们找到 fl1,i>r 并且 i 尽量大。因为 f 数组有单调性,所以二分这个 i 。可以做到 O(nBlogB)

看起来比较简单,但是没有那么好想。我想了半小时(可能是我菜)。

中规中矩的是 [l,r] 内是大数,区间外是小数。

下文中的 f 数组与上述定义一致。

我们对于一个左端点,枚举 fl1,i(iB) ,所以需要找到 [l,fl,i1] 有多少个 al ,我们记录了一个桶还记得吗,所以可以直接 O(1) 算。

时间复杂度 O(nB)

综上所述,我们可以想一下 B 怎么取,当 nBlogB=n2B 的时候达到了最优,得出 B2logB=n 。当 n=2×105 时,B 可以取 400 ,此时理论运算量来到了 108 ,可以卡常通过。

posted @   Diavolo-Kuang  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示