(Prefix suffix + thinking + greedy)
D. Grime Zoo
Question portal:
Main idea:
Give you a composition consisting of '0' and '1' and'?', in which a 01 sub-sequence will produce x-point anger value. For every 10 subsequences, y points of anger will be generated. The question mark'?' can be changed to 0 or 1. Ask what the minimum sum of anger is.
Ideas:
After learning from the ideas of many people, I personally understand the idea better:
when the number of 0 and 1 in a sequence is fixed, the number of subsequences 00 and 11 is also fixed, and the number of subsequence 01+10 is also fixed. of. Then when x>y, we greedily want as few 01 as possible and as many 10 as possible, so we fill in 1 as far forward as possible. When x<y, we want as many 01 as possible and as few 10 as possible, so we fill in 1 as far as possible. See the code for specific implementation details.
AC Code
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+10;
char str[N];
LL x,y;
int st[N][3],ed[N][3];//记录每个位置之前0,1,'?'的数量
vector<int>g;//存下每个问号的位置
int main()
{
scanf("%s",str+1);
scanf("%lld%lld",&x,&y);
int len=strlen(str+1);
for(int i=1;i<=len;i++)
{
//求前缀
st[i][0]=st[i-1][0];
st[i][1]=st[i-1][1];
st[i][2]=st[i-1][2];
if(str[i]=='0') st[i][0]++;
else if(str[i]=='1') st[i][1]++;
else
{
st[i][2]++;
g.push_back(i);
}
}
for(int i=len;i>=1;i--)
{
//求后缀
ed[i][0]=ed[i+1][0];
ed[i][1]=ed[i+1][1];
ed[i][2]=ed[i+1][2];
if(str[i]=='0') ed[i][0]++;
else if(str[i]=='1') ed[i][1]++;
else ed[i][2]++;
}
LL num0=0,num1=0;//记录前缀中0和1的数量(先把'?'都先看成是1)
LL ans=0;
for(int i=1;i<=len;i++)
{
if(str[i]=='0')
{
ans=ans+num1*y;
num0++;
}
else
{
ans=ans+num0*x;
num1++;
}
}
LL res=ans;
if(x<y)//10的愤怒值贡献高,所以我们尽量把1放在后面
{
for(int i=0;i<g.size();i++)//从前往后遍历每个问号的位置,并把它变成0
{
int idx=g[i];
res=res-(st[idx-1][0]+st[idx-1][2])*x-ed[idx+1][0]*y;
res=res+st[idx-1][1]*y+(ed[idx+1][1]+ed[idx+1][2])*x;
ans=min(res,ans);
}
}
else
{
//01的愤怒值高,所以我们尽量把1放前面
for(int i=g.size()-1;i>=0;i--)
{
//从后往前遍历问号的位置,并把它变成0
int idx=g[i];
res=res-st[idx-1][0]*x-(ed[idx+1][0]+ed[idx+1][2])*y;
res=res+(st[idx-1][1]+st[idx-1][2])*y+ed[idx+1][1]*x;
ans=min(res,ans);
}
}
printf("%lld\n",ans);
//system("pause");
return 0;
}