CF1693F I Might Be Wrong 题解

Description

给定一个长度为 nn01 字符串 SS
你可以进行下列操作任意次:

  • 选择 SS 的一个连续子串 S[l,r]S[l,r]
    cnt0,cnt1cnt_0,cnt_1 分别表示该子段中字符 0 和字符 1 的数量。
    则你将花费 cnt0cnt1+1|cnt_0-cnt_1|+1 枚金币并对 S[l,r]S[l,r] 进行升序排序。

你需要求出使 SS 本身升序排序所需的最少金币数。

n2×105n\leq 2\times 10^5

Solution

首先如果 cnt0<cnt1cnt_0<cnt_1,则可以让所有数反转并翻转整个序列,容易发现答案是不变的。现在 cnt0cnt1cnt_0\geq cnt_1

经过手玩可以发现每次都是选择 cnt0=cnt1cnt_0=cnt_1 的区间进行操作。

证明

d=cnt0cnt1d=cnt_0-cnt_1,现在需要证明可以通过不超过 d+1d+1cnt0=cnt1cnt_0=cnt_1 操作将整个序列排序。

如果 a1=0a_1=0,则把第一个数删掉后可归纳为 d1d-1 的问题。

如果 a1=1a_1=1,由于 cnt0>cnt1cnt_0>cnt_1,所以必然存在一个前缀使得其 0011 的个数相等,操作这个前缀并把第一个 00 删掉也可归纳为 d1d-1 的问题。

得到这个结论后就可以贪心地选择以当前第一个 1 为左端点的最长区间进行操作。

实现时维护一个数组 lstilst_i 表示最后一个前缀 cnt0cnt1=icnt_0-cnt_1=i 的位置即可。

时间复杂度:O(n)O(n)

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <bits/stdc++.h>

// #define int int64_t

const int kMaxN = 2e5 + 5;

int n;
int a[kMaxN], lst[kMaxN];
std::string s;

void dickdreamer() {
std::cin >> n >> s;
int cnt[2] = {0};
for (int i = 1; i <= n; ++i) {
a[i] = s[i - 1] - '0';
++cnt[a[i]];
}
if (cnt[0] < cnt[1]) {
std::swap(cnt[0], cnt[1]);
std::reverse(a + 1, a + 1 + n);
for (int i = 1; i <= n; ++i) a[i] ^= 1;
}
for (int i = 0; i <= n; ++i) lst[i] = 0;
for (int i = 1, sum = 0; i <= n; ++i) {
sum += (!a[i] ? 1 : -1);
if (sum >= 0) lst[sum] = i;
}
int ans = 0, pos = 0;
for (; pos < n && a[pos + 1] == 0; ++pos) {}
if (pos == cnt[0]) return void(std::cout << "0\n");
for (; pos < cnt[0] - cnt[1];) {
if (!lst[pos]) break;
pos += (lst[pos] - pos) / 2, ++ans;
}
std::cout << ans + 1 << '\n';
}

int32_t main() {
#ifdef ORZXKR
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
int T = 1;
std::cin >> T;
while (T--) dickdreamer();
// std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
return 0;
}

CF1693F I Might Be Wrong 题解
https://sobaliuziao.github.io/2025/03/22/post/d828b826.html
作者
Egg_laying_master
发布于
2025年3月22日
许可协议