题解:AT_abc346_d [ABC346D] Gomamayo Sequence
思路
一眼 。(虽然听说前缀和也能做?)
我们设 表示 和 位置都变为 。
如果我们枚举 ,再去推,显然会超时。
不如看一组样例:
01011101
如果我们把 和 位置都变为 ,这样会:
01001010
如果把 和 位置都变为 ,发现:
01011010
会发现只有 位置发生了变化。
同理,如果我们把 和 位置都变为 ,把 和 位置都变为 ,都满足这个定律。
推广后,发现在整个序列都满足该定律,即改变 和 位置为 到改变 和 位置为 只需要改变 位置的代价。把 和 交换同理。
这样,我们只需要算出把 和 位置改变的代价,就可以 的时间复杂度推出来了。
转移方程:
- 若 ,则 ,;
- 若 ,则 ,;
就结束了。
Code
#include<bits/stdc++.h>
using namespace std;
long long f[200005][2];
int n,c[200005],a[200005],a1[200005],a0[200005];
string s;
int main(){
cin>>n>>s;
for(int i=1;i<=n;i++)cin>>c[i];
for(int i=0;i<s.length();i++){
a[i+1]=s[i]-'0';
}
a0[1]=0;a0[2]=0;
a1[1]=1;a1[2]=1;
for(int i=3;i<=n;i++){
if(a0[i-1]==0)a0[i]=1;
else a0[i]=0;
if(a1[i-1]==1)a1[i]=0;
else a1[i]=1;
}
long long sum0=0,sum1=0;
for(int i=1;i<=n;i++){
if(a0[i]!=a[i])sum0+=c[i];
if(a1[i]!=a[i])sum1+=c[i];
}
f[1][0]=sum0,f[1][1]=sum1;
for(int i=2;i<n;i++){
f[i][1]=f[i-1][0];
f[i][0]=f[i-1][1];
if(a[i]==0){
f[i][1]+=c[i];
f[i][0]-=c[i];
}
else{
f[i][1]-=c[i];
f[i][0]+=c[i];
}
}
long long ans=9223372036854775807;
for(int i=1;i<n;i++){
if(f[i][1]<ans)ans=f[i][1];
if(f[i][0]<ans)ans=f[i][0];
}
cout<<ans;
return 0;
}

浙公网安备 33010602011771号