agc052E 3 Letters

Description

Solution

  • 首先由于相邻的都不一样,能不能用特殊的方法表示 S S S呢?如果看作是在模3的情况下,我们可以发现相邻的要么是+1要么是-1,因此 S S S等价一个数组 a a a a i % 3 = S i a_i\%3=S_i ai%3=Si ∣ a i − a i − 1 ∣ = 1 |a_i-a_{i-1}|=1 aiai1=1,在 a 1 a_1 a1确定的时候唯一确定。
  • 而操作可以看作将 a i a_i ai加或减2,并且要求之后还满足上面的条件。
  • 现在我们要把 S S S对应的 a a a变成 T T T对应的 b b b,首先 a 1 = b 1 ( m o d   2 ) a_1=b_1(mod\ 2) a1=b1(mod 2),因此对于所有 i i i都有 a i = b i ( m o d   2 ) a_i=b_i(mod\ 2) ai=bi(mod 2)。由于 a , b a,b a,b写成函数图像的优美的性质并不会在非整点相交,考虑在交点处分成若干个独立的段,不妨设 a i > b i a_i>b_i ai>bi在这一段满足,那么每一次将最大值减去2一定仍满足条件,因此可以得到 a n s = ∑ ∣ a i − b i ∣ 2 ans=\sum\frac{|a_i-b_i|}{2} ans=2aibi
  • 但是注意到 a 1 , b 1 a_1,b_1 a1,b1未确定,因此固定 a 1 a_1 a1枚举 b 1 b_1 b1计算最小的 a n s ans ans.预处理 a i − b i a_i-b_i aibi的分界点讨论正负即可做到 O ( n ) O(n) O(n)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 500105
#define ll long long
using namespace std;

int n,i,j,k,a[maxn],b[maxn],S[maxn],T[maxn];
vector<int> D[maxn];
char ch;
ll ans,sum,cnt;

int main(){
	freopen("ceshi.in","r",stdin);
	scanf("%d",&n),ch=getchar();
	while (ch<'A'||ch>'C') ch=getchar();
	for(i=1;i<=n;i++) S[i]=ch-'A',ch=getchar();
	while (ch<'A'||ch>'C') ch=getchar();
	for(i=1;i<=n;i++) T[i]=ch-'A',ch=getchar();
	for(i=2;i<=n;i++) {
		if (S[i-1]+S[i]==2) a[i]=(S[i-1]>S[i])?1:-1;
		else a[i]=(S[i-1]<S[i])?1:-1;
	}
	for(i=2;i<=n;i++) {
		if (T[i-1]+T[i]==2) b[i]=(T[i-1]>T[i])?1:-1;
		else b[i]=(T[i-1]<T[i])?1:-1;
	}
	a[1]=S[1]; for(i=2;i<=n;i++) a[i]+=a[i-1];
	for(i=0;i<6;i++) if (i%3==T[1]&&((i-a[1])&1^1)) b[1]=i;
	b[1]-=(n/3+3)*6;
	for(i=2;i<=n;i++) b[i]=b[i-1]+b[i];
	for(i=1;i<=n;i++) D[(a[i]-b[i]+5)/6].push_back(i);
	for(i=1;i<=n;i++) sum+=a[i]-b[i];
	ans=sum;  cnt=n;
	for(i=1;i<=2*n/3+3;i++) {
		sum=sum-cnt*6+(n-cnt)*6;
		for(j=0;j<D[i].size();j++){
			k=D[i][j],cnt--;
			sum=sum+6-abs(a[k]-(b[k]+(i-1)*6))+abs(a[k]-(b[k]+i*6));
		}
		ans=min(ans,sum);
	}
	printf("%lld\n",ans/2);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值