题解:AT_abc346_d [ABC346D] Gomamayo Sequence

思路

一眼 dp\tt dp。(虽然听说前缀和也能做?)

我们设 fi,0/1f_{i,0/1} 表示 iii+1i+1 位置都变为 0/10/1

如果我们枚举 ii,再去推,显然会超时。

不如看一组样例:

01011101

如果我们把 3344 位置都变为 00,这样会:

01001010

如果把 4455 位置都变为 11,发现:

01011010

会发现只有 44 位置发生了变化。

同理,如果我们把 3344 位置都变为 11,把 4455 位置都变为 00,都满足这个定律。

推广后,发现在整个序列都满足该定律,即改变 i1i-1ii 位置为 00 到改变 i+1i+1ii 位置为 11 只需要改变 ii 位置的代价。把 0011 交换同理。

这样,我们只需要算出把 1122 位置改变的代价,就可以 O(n)\operatorname{O}(n) 的时间复杂度推出来了。

转移方程:

  • si=0s_i=0,则 fi,0=fi1,1cif_{i,0}=f_{i-1,1}-c_ifi,1=fi1,0+cif_{i,1}=f_{i-1,0}+c_i
  • si=1s_i=1,则 fi,0=fi1,1+cif_{i,0}=f_{i-1,1}+c_ifi,1=fi1,0cif_{i,1}=f_{i-1,0}-c_i

就结束了。

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;
}
posted @   Weslie_qwq  阅读(2)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示