1. 程式人生 > 其它 >C. Binary String

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<bits/stdc++.h>
#include<unordered_map>
#include<algorithm>
#include<map>
#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<bits/stdc++.h>
#include<unordered_map>
#include<algorithm>
#include<map>
#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();
	}
}