D. Grime Zoo (accumulate的使用,累加函数的使用。) 贪心&&前缀

传送门

题意:

给你一个串,其中由 0 , 1 , ? 0, 1,? 0,1,?组成。

  1. 对于01的贡献是x
  2. 对于10的贡献是y

思路:

  1. 首先对于问号的位置,可以枚举一个位置,之后贪心的涂一个前缀即可。
  2. 主要是遍历 时,怎么快速计算出(下面以计算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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值