B. Ugu
B. Ugu
A binary string is a string consisting only of the characters and . You are given a binary string . It is necessary to make this string non-decreasing in the least number of operations. In other words, each character should be not less than the previous. In one operation, you can do the following:
- Select an arbitrary index in the string;
- For all , change the value in the -th position to the opposite, that is, if , then make , and vice versa.
What is the minimum number of operations needed to make the string non-decreasing?
Input
Each test consists of multiple test cases. The first line contains an integer — the number of test cases. The description of test cases follows.
The first line of each test cases a single integer — the length of the string.
The second line of each test case contains a binary string of length .
It is guaranteed that the sum of over all test cases does not exceed .
Output
For each test case, output a single integer — the minimum number of operations that are needed to make the string non-decreasing.
Example
input
8 1 1 2 10 3 101 4 1100 5 11001 6 100010 10 0000110000 7 0101010
output
0 1 2 1 2 3 1 5
Note
In the first test case, the string is already non-decreasing.
In the second test case, you can select and then .
In the third test case, you can select and get , and then select . As a result, we get , that is, a non-decreasing string.
In the sixth test case, you can select at the first iteration and get . Then choose , then . Then we select , getting the non-decreasing string .
解题思路
先说一下官方的题解。
构造一个数组,其中如果,则;否则如果,则。其中。这就是一个异或的差分数组。
如果反转位置上的数,那么区间内的数都要反转,根据差分的性质可以发现这个操作对数组的影响是只有发生了改变(变或变)。
对于一个非递降的序列,可以发现对于的数组要么全是,要么只有一个。全意味着整个都是同一类字符,只有一个意味着这个序列是 00 ... 01 ... 111 这种形式。
这时我们统计整个数组(区间)中的个数。如果字符串的首字母即,那么此时中最多只能有一个,其余的我们都要通过操作变成,因此对于这种情况的答案就。如果字符串的首字母即,那么此时中只能含有一个(也就是首字符的),其余的(区间)我们都要通过操作变成,因此对于这种情况的答案就。
补充,这题是怎么想到用差分的呢。实际上,当区间内的数反转时,等价于对这个区间内的每一个数进行模加法(加再对得到的值模),因此就是对某个区间内的每个数加上一个数的问题,因此想到差分。由于最终整个序列是非递降的,因此对应的差分数组应该最多包含一个,而每次对区间进行模加法,等价于对应的差分数组的第个位置进行模加法(第个位置可以忽略)。因此直接统计原始序列的差分数组中多余的的个数就可以了。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 2e5 + 10; 5 6 char str[N]; 7 8 void solve() { 9 int n; 10 scanf("%d %s", &n, str + 1); 11 12 int cnt = 0; 13 for (int i = n; i; i--) { 14 cnt += (str[i] & 1) ^ (str[i - 1] & 1); 15 } 16 17 int ret; 18 if (str[1] == '0') ret = max(0, cnt - 1); 19 else ret = cnt - 1; 20 21 printf("%d\n", ret); 22 } 23 24 int main() { 25 int t; 26 scanf("%d", &t); 27 while (t--) { 28 solve(); 29 } 30 31 return 0; 32 }
另外一种解法是参考其他人的。
对于字符串我们进行去重操作,比如有,那么去重后就是,即把连续相同的一段都用这一段中的首个数字来表示,统一把操作归到首个数字。
可以发现去重后得到的结果只有两种,要么是从开始的交替序列,要么是从开始的交替序列。
对于从开始的序列,很明显最优解是从第个位置开始每一个位置都置换一次,因此答案为。
对于从开始的序列,先考虑置换第个位置,那么就会得到从开始的交替序列,接着从第个位置开始置换后面每一个位置,因此这种方式的最优解为。如果不置换第个位置,那意味着整个序列要均为,那么从第个位置开始每个位置都要置换,因此答案就是。可以发现这两种方式得到的最优解是一样的,那么我们规定只要遇到那么就对这个位置上的数进行置换。
在实际实现中我们并不需要把去重的结果求出来,直接枚举原字符串就可以了,只要遇到就进行置换。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 2e5 + 10; 5 6 char str[N]; 7 int s[N]; 8 9 void solve() { 10 int n; 11 scanf("%d %s", &n, str + 1); 12 memset(s, 0, sizeof(s)); 13 for (int i = n; i; i--) { 14 s[i] = s[i + 1] + (str[i] & 1); // 求后缀1个个数 15 } 16 17 int ret = 0; 18 for (int i = 1, t = 0; i <= n; i++) { // t代表置换的累加次数 19 if (!t && s[i] == n - i + 1) break; // 如果置换了偶数次,并且[i, n]中全为1,那么就不用再置换了 20 if (t && !s[i]) break; // 如果置换了奇数次,并且[i, n]中全为0(等价于置换后全为1),也不用置换了 21 if ((str[i] & 1) ^ t) ret++, t ^= 1; // 遇到1就置换 22 } 23 24 printf("%d\n", ret); 25 } 26 27 int main() { 28 int t; 29 scanf("%d", &t); 30 while (t--) { 31 solve(); 32 } 33 34 return 0; 35 }
参考资料
Codeforces Round #830 (Div. 2) Editorial:https://codeforces.com/blog/entry/108327
Codeforces Round #830 (Div. 2)A、B、C1、D1(C2、D2待补):https://zhuanlan.zhihu.com/p/576542239
差分的应用:https://www.cnblogs.com/onlyblues/p/16282454.html
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16821610.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效