C. Binary String
阿新 • • 發佈:2022-05-16
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(); } }