agc019D Shift and Flip 【思维】

题目链接:https://agc019.contest.atcoder.jp/tasks/agc019_d

题意:
对01字符串A有三种操作:左移一位、右移一位,若另一个01字符串B的某一位为1,则A的该位可以 xor 1,问A到B至少要几次操作

吐槽:
这几天做了不少题。。懒得放上来了,写几个比较好的题吧。。
第6次把while打成if…于是自闭了好久

题解:
首先枚举A最后在什么位置与B重合,设最终位置为S
对比A[i]与B[(i+S)%n],就知道哪些位需要异或了
可以预处理出B的所有位向左向右(假设是一个环)所到的第一个1处,显然到第二个及以后的1不会更优,这就是可能需要A对应位异或1的位置
设第cur位左右分别到达的位置是left、right(之所以都需要走到左、右是因为如果只向左(右)走的话,有可能一些位置走不到(或距离变大)),则left<=cur<=right,有一个显然的关系:最终走的路程=2*(right-left)-|S|。证明就是按照S>=0 && S<0 分类讨论一下,画下图就很明白了吧…【注:这里的S>=0是参照cur来说的,实际上就是S>=cur && S<cur】
当S>=0时,ans=2*(right-left)-S,但是这里left<S && right>=S不太好处理,有一种神奇的方法:令X=-left,Y=right-S,则原式=2*(Y+X+S)-S=2*(Y+X)+S,且X>=0 && Y>=0,直接上手维护即可
这题数组下标以0开始为好,不然细节很多

代码:

// by Balloons
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#include <string>
#define debug() puts("okkkkkkkk")
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
 
using namespace std;
 
typedef long long LL;
 
const int inf = 1 << 30;
const int maxn=100005;
 
char a[maxn],b[maxn];
int ans=inf;
int lf[maxn],ri[maxn],mx[maxn];
int n;
 
void solve(){
	memset(ri,0,sizeof ri);memset(lf,0,sizeof lf);
	for(int i=0;i<n;i++){
		while(b[(i+ri[i])%n]=='0')++ri[i];
		while(b[(i+lf[i]+n)%n]=='0')--lf[i];
	}
	for(int s=0;s<n;s++){
		memset(mx,0,sizeof mx);
		int dif=0;
		for(int r=0;r<n;r++){
			if(a[r]!=b[(r+s)%n]){
				mx[-lf[r]]=max(mx[-lf[r]],ri[r]-s),++dif;
			}
		}
		int cur=0,tmp=inf;
		for(int i=n-1;i>=0;i--){
			tmp=min(tmp,cur+i);
			cur=max(cur,mx[i]);
		}
		ans=min(ans,2*tmp+s+dif);
	}
}
 
int main(){
	scanf("%s",a);scanf("%s",b);
	n=strlen(a);
	int cnta=0,cntb=0;
	for(int i=0;i<n;i++)if(a[i]=='1')++cnta;
	for(int i=0;i<n;i++)if(b[i]=='1')++cntb;
	if(cntb==0){	// 特判 
		if(cnta==0)puts("0");
		else puts("-1");
		return 0;
	}
	solve();
	reverse(a,a+n);
	reverse(b,b+n);
	solve();
	printf("%d\n",ans);
 
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值