CF EDU 128 C - Binary String
阿新 • • 發佈:2022-05-23
C - Binary String
找性質
一開始沒思路,想到可能跟字首和,字尾和有關,就先試一下
設 \(pre0\) 為 \(0\) 的個數的字首和,其他同理
先求出一開始的代價,即 \(0\) 的個數,設為 \(cnt\), 當前代價也是 \(cost=cnt\)
假設從前面刪到下標為 \(i\) ,從後面刪到下標為 \(j\) 是最優的
那答案就是 \(max(cost-pre0[i]-suf0[j],pre1[i]+suf1[j]])\)
隨著刪的越來越多 \(i\) 增大 \(j\) 減小,第一項單調遞減,第二項單調遞增
因此在 第一項 == 第二項 的時候是最優的
\(cost-pre0[i]-suf0[j]=pre1[i]+suf1[j]]\)
即 \(cost=pre0[i]+pre1[i]+suf0[j]+suf1[j]=i+n-j+1\)
所以可以找到最優解的一個重要性質:刪掉的個數 == 一開始的代價,即 \(0\) 的個數
最後列舉列舉從前面刪 \(i\) 個,\(0<=i<=cnt\) , 求出最小值即可
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <cmath> using namespace std; typedef long long ll; const int N = 2e5 + 10; string s; int pre0[N], pre1[N], suf0[N], suf1[N]; int main() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); int T; cin >> T; while(T--) { cin >> s; int n = s.size(); s = " " + s; suf0[n+1] = suf1[n+1] = 0; for (int i = 1; i <= n; i++) { pre0[i] = pre0[i-1] + (s[i] == '0'); pre1[i] = pre1[i-1] + (s[i] == '1'); } for (int i = n; i >= 1; i--) { suf0[i] = suf0[i+1] + (s[i] == '0'); suf1[i] = suf1[i+1] + (s[i] == '1'); } int cnt = pre0[n], cost = pre0[n]; for (int i = 0; i <= cnt; i++) { int now = max(cost - pre0[i] - suf0[n - cnt + i + 1], pre1[i] + suf1[n - cnt + i + 1]); cost = min(cost, now); } cout << cost << endl; } return 0; }