B. Grime Zoo 题解(贪心)

题目链接

题目大意

就是贪心的思路

最优解的一定是:前缀的?全部为1/0,后缀的?全部为0/1

根据\(x,y\)的大小来确定前缀和后缀的01

然后实现起来发现一个jls的写法很巧妙,只要记录数量以及和即可

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=1e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
char s[maxn];
ll x,y;
ll c0,s0,c1,s1;
signed main(){
    scanf("%s %lld %lld",s+1,&x,&y);
    int n=strlen(s+1);
    if(x>y){
        swap(x,y);
        for(int i=1;i<=n;i++){
            if(s[i]=='0'){
                s[i]='1';
            }else if(s[i]=='1'){
                s[i]='0';
            }
        }
    }
    vector<int> vec;
    for(int i=1;i<=n;i++){
        if(s[i]=='0'){
            c0++;
            s0+=i;
        }else if(s[i]=='1'){
            c1++;
            s1+=i;
        }else if(s[i]=='?'){
            c1++;
            s1+=i;
            vec.push_back(i);
        }
    }
    ll ans=1e18;
    for(int i=0;i<vec.size();i++){
        ans=min(ans,(s1-c1*(c1+1)/2)*x+(s0-c0*(c0+1)/2)*y);
        c0++,c1--;
        s0+=vec[i],s1-=vec[i];
    }
    ans=min(ans,(s1-c1*(c1+1)/2)*x+(s0-c0*(c0+1)/2)*y);
    printf("%lld\n",ans);
    return 0;
}


posted @ 2021-09-06 19:58  hunxuewangzi  阅读(34)  评论(0编辑  收藏  举报