传送门
题意:
给你一个串,其中由 0 , 1 , ? 0, 1,? 0,1,?组成。
- 对于01的贡献是x
- 对于10的贡献是y
思路:
- 首先对于问号的位置,可以枚举一个位置,之后贪心的涂一个前缀即可。
- 主要是遍历 时,怎么快速计算出(下面以计算10为eg)
对于一个合法的10那么我们只要找到所有的0的位置。
cnt = p 0 [ i ] p_0[i] p0[i] - i i i(减去前面是1的位置)
那么总结一下就是 ( ∑ i = 1 t o t p 0 [ i ] ) − ( t o t + 1 ) ∗ ( t o t ) 2 (\sum_{i=1}^{tot} p_0[i]) - \frac{(tot+1)*(tot)}{2} (∑i=1totp0[i])−2(tot+1)∗(tot)
又学了一个函数
accumulate
accumulate(v.begin(),v.end(),init)//init为累加的初始值。
#include <iostream>
#include <bits/stdc++.h>
#define For(i,x,y) for(int i = (x); i <= (y); i ++ )
#define fori(i,x,y) for(int i = (x); i < (y); i ++ )
#define mp make_pair
#define fi first
#define se second
#define pb push_back
#define sz(a) (int)a.size()
#define endl '\n'
#define all(a) a.begin(), a.end()
#define mst(x,a) memset(x, a, sizeof x)
#define debug(a) cout<< #a <<": " << a << endl
using namespace std;
typedef long long LL;
typedef pair<int,int>pa;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
const int maxn = 2e5+10;
const int maxm = 1e6+10;
const int N = 1e6+10;
//#define LOCAL
int main()
{
ios::sync_with_stdio(0);
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif
string s; //cin>>s;
int x, y;
cin>>s>>x>>y;
LL cnt[3][3] {};
vector<int>p;
fori(i,0,sz(s)){
if(s[i] == '1') {
cnt[1][0]++;
cnt[1][1] += i;
}else if(s[i] == '0'){
cnt[0][0]++ ;
cnt[0][1] += i;
}else p.pb(i);
}
///初始的值
cnt[2][0] = sz(p);
cnt[2][1] = accumulate(all(p), (LL )0);
if(x >= y) {
swap(cnt[1][0],cnt[0][0]);
swap(cnt[1][1],cnt[0][1]);
swap(x,y);
}
LL ans = 9e18;
cnt[1][1] += cnt[2][1];
cnt[1][0] += cnt[2][0];
For(i,0,cnt[2][0]){
LL tmp = (cnt[0][1] - cnt[0][0]*(cnt[0][0] - 1)/2) * y + (cnt[1][1] - cnt[1][0]*(cnt[1][0] - 1)/2) * x;
ans = min(ans, tmp);
if(i < cnt[2][0]) {
cnt[0][0] ++;
cnt[0][1] += p[i];
cnt[1][0] -- ;
cnt[1][1] -= p[i];
}
}
cout<<ans<<endl;
return 0;
}