我们考虑到这道题的取反的个数的最小值是一定的,而进行2操作的个数最大值是一定的,是n-1个..所以我们枚举我们需要进行多少次2操作…然后计算出前缀和的最小值…计算出进行当前多个2操作时的最小答案…
代码如下:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
//by NeighThorn
using namespace std;
const int maxn=1000000+5;
int n,p,q,x,y,lala[maxn*2],que[maxn],hd,ta,calc[maxn];
long long ans,minsum[maxn],tot,tmp;
char s[maxn];
signed main(void){
scanf("%d%d%d%d%d%s",&n,&p,&q,&x,&y,s+1);
for(int i=n<<1;i>n;i--)
lala[i]=lala[i+1]+(s[i-n]=='+'?1:-1);tot=lala[n+1];
for(int i=n;i;i--)
lala[i]=lala[i+1]+(s[i]=='+'?1:-1);hd=1;ta=0;
for(int i=n<<1;i;i--){
while(hd<=ta&&lala[i]>lala[que[ta]])
ta--;
que[++ta]=i;
while(hd<=ta&&que[hd]-i>n)
hd++;
if(i<=n)
minsum[i]=lala[i]-lala[que[hd]];
}
ans=0x7f7f7f7f7f7f7f7fll;tot=q-p-tot;tot/=2;
for(int i=2;i<=n;i++)
calc[i]=n-i+2;calc[1]=1;
for(int i=0;i<n;i++){
long long tmp=i*y+abs(tot)*x;
minsum[calc[i+1]]+=p+max(tot,0ll)*2ll;
if(minsum[calc[i+1]]<0)
tmp+=((1-minsum[calc[i+1]])/2ll)*2*x;
ans=min(ans,tmp);
}
printf("%lld\n",ans);
return 0;
}
by >_< NeighThorn