Page Top

CF1884B Haunted House 题解

CF1884B Haunted House 题解

借鉴了当前 另一篇题解,加了更多的说明。

简化题意

给定一个长度为 \(n\) 的二进制串 \(S\),求 \(f(1),f(2),\cdots,f(n)\)

其中,\(f(i)\) 定义为,每次交换相邻的两个二进制位,将 \(S\) 的后 \(i\) 为全变为 \(0\) 的最小交换次数。

分析

特殊的,\(f(0)=0\)

假设我们已经求出了 \(f(i-1)\),那么就可以用 \(f(i-1)\) 步将后 \(i-1\) 位变为 \(0\)

然后考虑再处理一位。

先贪心的考虑这一位,一定是将这个 \(1\) 与后面的第一个 \(0\) 交换,而交换的花费为这两位的下标相减(需要依次交换这么多个相邻元素。

以上如果不理解的,可以自己手动模拟两个。

然后,为什么一位一位的考虑,就一定是最优解呢?

证明:这个操作方法,截至到每一位,后面所有的 \(1\) 一定会依次从后往前占用前面的 \(0\),而不存在比这更优的方法。

实现

两个指针,一个 \(i\) 记录当前的位置,一个 \(j\) 记录前面第一个 \(0\)

注意:每次都需要将 \(j\) 指针前移一位,表示这个 \(0\) 已经被占用。

代码

评测记录:https://codeforces.com/contest/1884/submission/230477092

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve(int n, string s) {
ll ans = 0;
for (int i = n - 1, j = n - 1; ~i; --i, --j) {
while (j >= 0 && s[j] == '1') --j;
if (j < 0) printf("-1 ");
else printf("%lld ", ans += i - j);
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T; cin >> T;
while (T--) {
int n; string s;
cin >> n >> s;
solve(n, s);
} return 0;
}
posted @   RainPPR  阅读(47)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示