| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> [ROI2018]无进位加法 -> 正文阅读 |
|
[数据结构与算法][ROI2018]无进位加法 |
题目题目背景 “我没什么可送你的,只能送你……” “十拳剑封印!” 从暗处出现的 D D ( X Y X ) \sf DD(XYX) DD(XYX) 忽然一刀结束了 O n e I n D a r k \sf OneInDark OneInDark 报团取暖的人生。“原谅我,小卷。我将作为你需要越过的标杆,永远地陪伴着你!” 真相却依旧在电线杆之上。电线杆上是 D D G \sf DDG DDG 的爪印,和四个未曾褪色的金字—— “非吾邮箱!” 题目描述 数据范围与约定 思路我一直思考怎样让 a i a_i ai? 增加,就全完蛋了。二分答案 的优点就在于 只问结果,不看过程。 假设我们已知 χ = ∑ b i \chi=\sum b_i χ=∑bi?,那么 { a i } \{a_i\} {ai?} 变化后得到的序列 { b i } \{b_i\} {bi?} 是对 χ \chi χ 的二进制位拆分。而合法的条件就是 b i ? a i b_i\geqslant a_i bi??ai? 呗!盍自讨苦吃,让 a i a_i ai? 一点点增大? 于是我们看出 χ 1 ? χ 2 \chi_1\subseteqq \chi_2 χ1??χ2? 时, χ 2 \chi_2 χ2? 更可能合法,因为对应的 b i b_i bi? 只会更大。所以二分答案法是可行的——从高位开始,逐个确定 χ \chi χ 的 b i t \rm bit bit,检验只需令后面的 b i t \rm bit bit 为全 1 1 1 。 怎样检验呢?找到 χ \chi χ 最高二进制位 p p p 。再找到 v = max ? a i v=\max a_i v=maxai? 。若 2 p + 1 ? v 2^{p+1}\leqslant v 2p+1?v,则 v v v 不可能对应合法 b i b_i bi?,失败。若 2 p > v 2^p>v 2p>v,则该位单独作为某个 b i b_i bi? 时,就可以与任意剩余 a i a_i ai? 匹配,贪心地想肯定是与 v v v 匹配;将 v v v 删掉,将 2 p 2^p 2p 从 χ \chi χ 中移除,继续进行该匹配。 若 v ∈ [ 2 p , 2 p + 1 ) v\in[2^p,2^{p+1}) v∈[2p,2p+1),则 2 p 2^p 2p 必须分配给 v v v 对应的 b i b_i bi?,并且这还不够用。将 v v v 的最高位,即 2 p 2^p 2p,与 χ \chi χ 中的 2 p 2^p 2p 一同移除,然后继续进行该匹配。 那么过程中, a i ′ a'_i ai′? 会是 a i a_i ai? 的一个后缀(较低的若干 b i t \rm bit bit 位)。为了找 max ? \max max,我们需要预处理其大小关系。从低位到高位做基数排序,就能确定相同长度的后缀之间的大小关系,于是可以 O ( ∑ L i ) \mathcal O(\sum L_i) O(∑Li?) 进行预排序。——由于 n ? ∑ L i n\leqslant\sum L_i n?∑Li?,其已被忽略。 上面的做法显然不够快。我们知道,在大小比较时,最高位起到决定性作用。于是我们设 k i k_i ki? 为 a i a_i ai? 的最高位,即 2 k i ? a i < 2 k i + 1 2^{k_i}\leqslant a_i<2^{k_i+1} 2ki??ai?<2ki?+1,考虑能不能搞出些幺蛾子。 答案的下界是 a i = 2 k i a_i=2^{k_i} ai?=2ki? 。不言而喻的前提是 a i a_i ai? 减小(或增大)不会得到更劣(或更优)的解。记 h h h 为 χ \chi χ 的最高 b i t \rm bit bit,设 { a i } \{a_i\} {ai?} 单调递减,我们震惊地发现 h = max ? ( i ? 1 + k i ) h=\max(i{-}1{+}k_i) h=max(i?1+ki?) 。因为用掉前 ( i ? 1 ) (i{-}1) (i?1) 个 1 1 1 的 b i t \rm bit bit 后,第 i i i 个的位置不能矮于 k i k_i ki? 。归纳法可知其可实现。 答案的上界是 a i = 2 k i + 1 a_i=2^{k_i+1} ai?=2ki?+1 。类型完全相同!此时 h = max ? ( i + k i ) h=\max(i{+}k_i) h=max(i+ki?),也就是上面的那个 h h h 再 + 1 +1 +1 。 回到原问题。记 h 0 = max ? ( i ? 1 + k i ) h_0=\max(i{-}1{+}k_i) h0?=max(i?1+ki?),我们只需要检验 h = h 0 h=h_0 h=h0? 是否可行,不可行则选取 h = h 0 + 1 h=h_0{+}1 h=h0?+1 。也就是说,我们可以直接造出最优解,所谓二分答案的过程则被废弃了。 考虑 h 0 h_0 h0? 究竟是谁的限制:找到最小的 t t t 使得 t ? 1 + k t = h 0 t{-}1{+}k_t=h_0 t?1+kt?=h0? 。由于处理 a t a_t at? 之前至少有 ( t ? 1 ) (t{-}1) (t?1) 个 b i t \rm bit bit 会被直接用掉,所以必须是 [ k t , h 0 ] [k_t,h_0] [kt?,h0?] 这些 b i t \rm bit bit 为全 1 1 1 。但同时我们又发现, t t t 是最小足以保证这些 b i t \rm bit bit 恰好让那些 a i ?? ( i < t ) a_i\;(i<t) ai?(i<t) 完成了匹配! 于是 a t a_t at? 与 k t k_t kt? 上的 b i t \rm bit bit 匹配,得到 a t a_t at? 移除 2 k t 2^{k_t} 2kt? 的结果。将 a i ?? ( i < t ) a_i\;(i<t) ai?(i<t) 移除,剩下的数字只能递归了。为了加速判断,我们同样先求出一个估计值 h 0 ′ h_0' h0′?,则实际值 h ′ ∈ { h 0 ′ , h 0 ′ + 1 } h'\in\{h_0',h_0'{+}1\} h′∈{h0′?,h0′?+1} 。合法的条件显然是 k t > h ′ k^t>h' kt>h′,互不干扰嘛。可以发现只有 k t = h 0 ′ + 1 k_t=h_0'{+}1 kt?=h0′?+1 时,合法性不确定,需要再顺着 t ′ t' t′ 递归检验。 我们还能窥见, h = h 0 + 1 h=h_0{+}1 h=h0?+1 时,必须是 ( k t + 1 , h ] (k_t{+}1,h] (kt?+1,h] 这些 b i t \rm bit bit 为全 1 1 1 。因为其他情况其实都递归到上面的 χ ′ , h ′ \chi',h' χ′,h′ 答案;该情况却能让 a t a_t at? 直接获得匹配,因而消失。所以求出 h h h 之后,我们就能造出最优解了。 时间复杂度是什么呢?若 h = h 0 h=h_0 h=h0? 成功,则递归过程没有回溯,每次至少将 a t a_t at? 的一个 b i t \rm bit bit 移除。若 h = h 0 h=h_0 h=h0? 失败,由于 k t ? 1 = h 0 ′ ? k t ′ k_t{-}1=h_0'\geqslant k_{t'} kt??1=h0′??kt′?,最多递归 O ( k t ) \mathcal O(k_t) O(kt?) 次,然后会将 a t a_t at? 移除。 于是记势能 Φ = ∑ k i \Phi=\sum k_i Φ=∑ki?,则两种情况的操作次数 ? \leqslant ? 势能减小量 Δ Φ \Delta\Phi ΔΦ 。所以总次数和就是 O ( Φ 0 ) = O ( ∑ L i ) \mathcal O(\Phi_0)=\mathcal O(\sum L_i) O(Φ0?)=O(∑Li?) 。 过程中 代码看上去还蛮简单的。
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 9:41:42- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |