CF1465D Grime Zoo

Description

Currently, XXOC's rap is a string consisting of zeroes, ones, and question marks. Unfortunately, haters gonna hate. They will write $x$ angry comments for every occurrence of subsequence 01 and $y$ angry comments for every occurrence of subsequence 10. You should replace all the question marks with 0 or 1 in such a way that the number of angry comments would be as small as possible.

String $b$ is a subsequence of string $a$, if it can be obtained by removing some characters from $a$. Two occurrences of a subsequence are considered distinct if sets of positions of remaining characters are distinct.

 

Solution

可以证明当$x < y$时,假如一对问号是1和0,当它们被0和1替换时一定不会使答案变劣

所以当$x<y$时,连续的两个?分别是0和1会达到最优

同理$x > y$时,连续的两个?分别是1和0会达到最优

考虑对一个随机的答案不断进行替换使它更优

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

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
long long x,y,prec[100005],sufc[100005],pre[100005],suf[100005],ans=1ll<<60,n;
char s[100005];
inline int read()
{
    int f=1,w=0;
    char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
    return f*w;
}
int main()
{
    scanf("%s",s+1),x=read(),y=read(),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';
    }
    for(int i=1;i<=n;i++)
        if(s[i]=='1') prec[i]=prec[i-1]+1,pre[i]=pre[i-1]+1ll*(i-prec[i])*x;
        else prec[i]=prec[i-1],pre[i]=pre[i-1]+prec[i]*y;
    for(int i=n;i;i--)
        if(s[i]=='0') sufc[i]=sufc[i+1]+1,suf[i]=suf[i+1]+1ll*(n-i+1-sufc[i])*x;
        else sufc[i]=sufc[i+1],suf[i]=suf[i+1]+sufc[i]*y;
    for(int i=0;i<=n;i++) ans=min(ans,pre[i]+suf[i+1]+prec[i]*sufc[i+1]*y+1ll*(i-prec[i])*(n-i-sufc[i+1])*x);
    printf("%lld\n",ans);
    return 0;
}
Grime Zoo

 

posted @ 2020-12-22 09:54  QDK_Storm  阅读(680)  评论(0编辑  收藏  举报