LuoguP5650 基础字符串练习题 题解
Update
- \(\texttt{2020.10.15}\) 修改了格式,并删除了 10 分,80 分的代码以及其他的一些废话,增加了笔者现在的题解格式中的 Content 部分。
Content
给出一个长度为 \(n\) 的 \(0/1\) 串,试求出所有子串中 \(0\) 的个数减去 \(1\) 的个数的最大值。
数据范围:\(1\leqslant n\leqslant 10^5\)。
Solution
原来做此题的过程已迁移到这篇文章上来,欢迎前往。
这里直接总结这道题目的做法:
用字符串输入完以后,处理整体的一段,并将它的贡献存储(比如样例就可以分成 \(0,1111,00,1,0,1\) 这六段,不难想出 \(0\) 对于最大值的贡献是 \(1\),\(1\) 对于最大值的贡献是 \(-1\),所以这六段根据它的贡献就变成了 \(1,-4,2,-1,1,-1\))。(注意!如果字串全是 \(1\) 要特判直接输出 \(-1\)!)
利用前缀和存储前 \(i\) 段的贡献。然后设总共的段数为 \(cnt\),每一段的贡献是 \(w[i]\),然后最终的答案就是 \(\max\begin{Bmatrix}w[r]-w[l-1]\end{Bmatrix}\),其中 \(l\in[1,cnt],r\in[l,cnt]\)。
Q&A
\(\texttt{Q1:}\) 贡献是什么意思?
\(\texttt{A1:}\) 对于这道题目来说,贡献就是对于这个 \(0\) 的个数减 \(1\) 的个数得到的最大值,\(0/1\) 在起的作用,通俗一点讲,\(0\) 是对于最大值有贡献的,\(1\) 对于这个最大值帮了倒忙。不难想出,\(0\) 的贡献是 \(1\),\(1\) 的贡献是 \(-1\)。
\(\texttt{Q2:}\) 为什么字串都是零的时候就要输出\(-1\)呢?
\(\texttt{A2:}\) 仔细看题,不难发现有一段说道:选出一个非空子串,而当字串全是 \(1\) 时,无论如何都要选出一个来,所以就只选一个 \(1\) 出来,答案就是\(-1\)。
Code
\(\color{yellow}\text{60}\color{Black}\text{ pts}\)(原谅我写了个 \(\texttt{DFS}\)):
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
string s;
int flag = 1, ans, len;
void dfs(int x, int sum) {
if(x > len) return;
ans = max(ans, sum);
dfs(x + 1, sum + (s[x] == '0' ? 1 : -1));
}
int main() {
cin >> s;
for(int i = 0; i < s.length(); ++i)
if(s[i] == '0') flag = 0;
if(flag) {
printf("-1");
return 0;
}
len = s.length();
for(int i = 0; i < len; ++i)
dfs(i, 0);
printf("%d", ans);
return 0;
}
\(\color{LimeGreen}\text{100}\color{Black}\text{ pts}\):
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
string s;
int flag = 1, ans, len, part[100007], cnt, sum[100007];
int main() {
cin >> s;
for(int i = 0; i < s.length(); ++i)
if(s[i] == '0') flag = 0;
if(flag) {
printf("-1");
return 0;
}
for(int i = 0; i < s.length(); ++i) {
if(i == 0) part[++cnt] += (s[i] - '0' == 0 ? 1 : -1);
else {
if(s[i] != s[i - 1]) part[++cnt] += (s[i] - '0' == 0 ? 1 : -1);
else part[cnt] += (s[i] - '0' == 0 ? 1 : -1);
}
}
for(int i = 1; i <= cnt; ++i)
sum[i] = sum[i - 1] + part[i];
for(int i = 1; i <= cnt; ++i)
for(int j = i; j <= cnt; ++j)
ans = max(ans, sum[j] - sum[i - 1]);
printf("%d", ans);
return 0;
}

浙公网安备 33010602011771号