C. Binary String


C. Binary String

https://codeforces.ml/contest/1680/problem/C

题意

给你一个01字符串 可以选择再最前面和最后面删除若干个0或1 然后取剩余的0的个数和删去的个数中较大的那个数作为答案 求最小答案

思路

二分 + 双指针 也可以直接双指针
二分答案 首先预处理计算出01串中1的个数 每次check时i从左到右遍历同时记录当前区段0和1的个数 如果0的个数大于check的值 那就将j++(i就相当于右边界 而j就相当于左边界) 每次当区域中0满足条件时 就去判断删去的1是否小于等于x(若是则说明答案可以更小直接return true)

#include
#include
#include
#include
#define ll long long
#define ull unsigned long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const ll inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-4;
const ll N = 2e5 + 5;
const int M = 1e6 + 5;
const ll mod = 1e9 + 7;
ll n, pre[N], sum;
string s;
//check 函数
bool check(ll x) {
	ll cnt1 = 0, cnt0 = 0;
	for (int i = 0, j = 0; i < s.size(); i++) {
		if (s[i] - '0') cnt1++;
		else cnt0++;
		while (cnt0 > x && j < s.size()) {
			if (s[j] - '0') cnt1--;
			else cnt0--;
			j++;
		}
		if (sum - cnt1 <= x) return true;
	}
	return false;
}

void solve() {
	
	cin >> s;
	sum = 0;
	for (int i = 0; i < s.size(); i++) {
		if(s[i] - '0') sum++;
	}
	ll l = 0, r = s.size(), ans = inf;
	while (l <= r) {
		ll mid = (l + r) / 2;
		if (check(mid)) {
			ans = mid;
			r = mid - 1;
		}
		else l = mid + 1;
	}
	cout << ans << "\n";
}
signed main() {
	IOS;
	int t = 1;
	cin >> t;	
	while (t--)
	{
		solve();
	}
}


双指针的做法
先预处理pre[i]数组 代表前i个含有多少个1 根据1的个数我们也可以算出0的个数
双指针l r都先从1开始 每次判断当前区段留下的0的个数和删去的1的个数(用pre[]数组可以很快得出) 如果删掉的1的个数更大那么右指针右移 这样可以使得留下更多0删去更少的1 若留下的0更多那么就左指针右移 让留下的0更少删去的1更多 每次都更新答案取min 最终输出答案即可

#include
#include
#include
#include
#define ll long long
#define ull unsigned long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const ll inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-4;
const ll N = 2e5 + 5;
const int M = 1e6 + 5;
const ll mod = 1e9 + 7;
ll n, pre[N];

void solve() {
	string s;
	cin >> s;
	pre[0] = 0;
	for (int i = 0; i < s.size(); i++) {
		pre[i + 1] = pre[i] + s[i] - '0';
	}
	ll ans = pre[s.size()];
	for (int l = 1, r = 1; r <= s.size() && l <= r; ){
		ll x = r - l + 1 - (pre[r] - pre[l - 1]);
		ll y = pre[s.size()] - (pre[r] - pre[l - 1]);
		if (x <= y) {
            ans = min(ans, y);
			r++;
		}
		else {
			ans = min(ans, x);
			l++;
		}
	}
	cout << ans << "\n";
}
signed main() {
	IOS;
	int t = 1;
	cin >> t;	
	while (t--)
	{
		solve();
	}
}