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;
}
posted @ 2021-12-23 21:00  Eason_AC  阅读(46)  评论(0)    收藏  举报