「loj - 2850」「ROI 2018 Day 2」无进位加法

link。

以前以为自己会证时间复杂度,后来考到原题发现自己证伪了,草。


从高到低确定 b 的每一位是否可以为 0

枚举第 p 位是否可以为 0 时,比第 p 位低的位全部填 1,比第 p 位高的保留不变,得到一个 b。之后看是否存在一个 {bi} 满足要求。

相当于我们需要把 b 的每个 1 分配给某个 i(也即,bi 的这一位为 1),使得 aibi

简单的观察:不妨设 a1a2an,则存在一个最优解满足 b1b2bn

由观察,考虑 b 最高位的 1,它一定分配给最大的 amax

如果 b 的最高位 h 大于 amax 的最高位 q,则 amax 接下来不需要被分配其他的 1,直接删掉。

如果 b 的最高位 h 等于 amax 的最高位 q,则需要把 amax 删去最高位后再塞回去(如果删掉最高位后非零的话)。

如果 b 的最高位 h 小于 amax 的最高位 q,则不合法,此时 b 的第 p 位填 0

当然,如果把所有 a 都删完了,则 b 的第 p 位填 1

显然,这一过程不需要每次都从最高位开始扫 b,比 p 高的位的影响保留下来,可以从第 p1 位开始往后扫。


某时刻的某个 a 一定是初始时的某个 ai 删去最高的若干个 1 的情况,因此在过程中 a 的可能情况只有 O(L) 种。

可以将这 O(L) 种可能的 a 拿出来排序,具体来说由于只有长度相同的需要排,做个基数排序即可(当然,由于这部分不是瓶颈,你也可以尝试一些 O((L)log(L)) 的排法)。


考虑某一时刻枚举到 b 的第 p 位。

设此时 a1a2an,并设 ai 的最高位为 ti。则合法的一个必要条件i,piti

分配给 ai1 最大也只能是 pi,还有可能因为前面的数需要删去最高位重新塞回来而变小。

另一方面,合法的一个充分条件i,pi>ti

此时所有数都可以直接被删掉。

那么事实上需要检验的只有 p=max{i+ti} 的情况。


我们找到使得 i+ti 最大的 i 中最小的 k=min{i}

如果 p=max{i+ti}0,则 a1ak 分别对应了 b 的第 p1pk 位上有 1

删掉 a1ak,插入 ak 删去最高位后的 ak,然后继续找 p=max{i+ti}

如果 pk>p,则前面的合法。

如果 pk<p,则前面的不合法。

如果 pk=p,我们令 p=p,令 k 为此时使得 i+ti 最大的最小 i,然后继续递归检验。

可以使用线段树维护查找最大值的过程。


然后可以证明,这样递归的总次数不会超过 O(L)。由于使用线段树维护,总复杂度为 O(Llog(L))

首先,相同长度的 ai 只会有一个最大的 i+ti。也即,我们每次选定的 ak 比上次递归进来的 ak 对应的长度要短。

因此,如果最开始需要检验的是 p,则递归次数实际上不会超过 O(Lp)

而对于每个串,它只有一次是“最开始”检验的。因此得证。

posted @   Tiw_Air_OAO  阅读(727)  评论(1编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示