CF1693F I Might Be Wrong 题解

感觉是一个比较套路的题目。

思路#

很容易就可以胡出一个贪心策略。

每一次操作都选一个从前面开始最长的 0,1 数量相同的序列进行操作。

看一眼好像样例都能过。

可以考虑如何来证明一下这个东西。

为了方便,首先我们假定操作序列中 0 的数量多于 1 的数量。

那么我们的操作就是要将所有在 1 中的 0 全部都移到左边。

很显然,我们的操作的每一段要么是 0 的数量多于 1 的数量,或者是 0 的数量等于 1 的数量(因为 0 的数量少于 1 的数量显然不优)。

0 的数量多于 1 的数量时。

整体所需要耗费的代价也就是 0 的数量多于 1 的数量的值,再加一。

我们将 0 的数量多于 1 的数量的值设为 k

那么,同样的,我们可以将此时的操作序列中进行 k 次在一个前缀满足 0 的数量等于 1 的数量的序列上进行操作,可以观察到,每一次操作后,至少会有一个 0 被移到左边,而每一次的代价均为 1

所以,可以发现,每一次都操作 0 的数量等于 1 的数量的序列一定不劣。

然后每一次都找最长的序列,就为最优的方案了。

然后就可以发现,我们的问题变为了给一个序列,需要不断的找到最长的 0 的数量等于 1 的数量的序列。

首先 O(nlogn) 的线段树是显然可以做的。

但由于这道题的最长的 0 的数量等于 1 的数量的序列需要满足必须包含整段中的第一个 1

我们就有可以想到一个比较套路的方法。

可以发现,我们的最后一次的操作一定是包含所有的 1 的一个序列。

所以,我们可以假设 1,0 的个数差是 d

那么问题又可以转化为将一个序列使得前面大于等于 d 个数为 0

考虑到我们每次的操作的右端点是单调递增的。

所以每一次我们的操作都是不会影响到前缀值。

可以预处理出前面 0 的个数比 1 的个数多的值的最后一个位置。

这样就可以不断的利用前缀转移,时间复杂度 O(n)

Code#

代码就不放了,还是比较好实现的。

作者:JiaY19

出处:https://www.cnblogs.com/JiaY19/p/16791545.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   JiaY19  阅读(97)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示