只是在证明前简述了做法,应该不算评论区发题解吧,而且唯一一篇这个复杂度没证明的题解也压在最下面估计没人看。
全是自己口胡的,没写过,应该没假吧。
算法概述
可以容易地感受到 >n 且 ⩽nlogn 的部分用暴力依然有点浪费,>nlogn 且 <nlogn 的二分也有点浪费。
令 ai 为答案 ⩾i 的 k 右端点,我们考虑从 ai+1 推出 ai。
类似 finger search,我们在倍增时先不断尝试 +1,+2,+4,+8,… 直至失败,然后向下枚举 2 的幂尝试 …,+8,+4,+2,+1。复杂度为 Θ(log(ai+1−ai+1)) 次检验与 Θ(1) 的额外复杂度而无法全部取到 Θ(logn)。而且可以利用失败的查询做一些优化,这里不赘述(类似 ai=ai+1 检验一次后即可跳过后续相同检验,除了这个在 i>n 的表现之外均为常数优化,注意自上而下二分虽然跑满但若视作一倍常数,finger search 具有两倍常数,复用了信息后应该和整体二分相比只是跳的步长对齐了 2 的幂)。
复杂度证明
因此我们需要的复杂度分析相当于:a0=n,an+1=0,∀i∈[1,n]∩N,ai∈[ai+1,n/i]∩N,最大化 ∑i=1nlog(ai−ai+1+1)。
注意到若 ai−ai+1⩽ai+1−ai+2 时交换 ai−ai+1 与 ai+1−ai+2 仍满足约束且不影响结果,因此不妨假设 ai−ai+1⩾ai+1−ai+2。我们可以从 ∀i∈[1,n]∩N,ai=⌊n/i⌋ 开始,每次对 ai−ai+1⩾ai+1−ai+2>0 的某个 i∈[0,n)∩N 执行 ai+1←ai+1−1 得到任意满足上述约束的 a。具体地:
-
注意到 a⌊n⌋⩽n/⌊n⌋,∑i=⌊n⌋nlog(ai−ai+1+1)=O(n)。
-
注意到对于 2⩽x⩽y,log(x−1)+log(y+1)⩽logx+logy。
-
注意到 ∫1nlog(n/x−n/(x+1))dx=∫1nlog(n/(x2+x))dx=Θ(n)。
洛谷还是有题解是正确的 Θ(nn) 的,只是没写证明:https://www.luogu.com.cn/article/f9wksdt9。整体二分与上述做法本质上基本相同,只是离线后交换了一些检验顺序。