Agc019_D Shift and Flip
题目大意
给定两个长为$n$的$01$串$A,B$,每次操作有三种
将$A$整体向左移动,并将$A_1$放在原来$A_n$的位置上。
将$A$整体向有移动,并将$A_n$放在原来$A_1$的位置上。
选择一个位置$i$使得$B_i=1$,将$A_i$变为$1-A_i$。
求将$A$变为$B$的最小操作数,若无解输出$-1$。
$n\leq 2000$
题解
首先当$A$有$1$,$B$没有$1$那么一定无解。当$A,B$均没有$1$时代价为$0$
其余情况$B$中一定有$1$,将$A$的环状移动用将$B$左右倍长为$3$倍,$A$直接左右移动。
对于$A$中每一个位置$i$,预处理每一个$i$需要向左和向右最少移动多少步才能使得$A_i$对应了一个$B_j$使得$B_j=1$,记为$L_i,R_i$。
接着,考虑暴力枚举最终$A$在与原来的相对位置与$B$对应,假设$A$与原来的位置相对向右移动了$k$个,然后对于每一个$A_i\ne B_{i+k}$,我们至少将$A$左移$L_i$位或右移$R_i$。
假设我们最终要向右移动$k$位与$B$对应,考虑枚举先向左走了$x$步,那么对于所有$L_i\leq x$对答案无影响了,只需要统计对$L_i>x$的$R_i$最大值(记为$RS$),那么但就是先向左移$x$步再移回来,再向右移到$RS$,最后移到$k$显然是最优的方案,过程中要对哦每一个$A_i\ne B_{i+k}$的进行一步操作,记为$m$个,那么就用$2x+RS+|RS-k|+m$来更新答案。
将$A$向左移动同理。
复杂度$O(n^2)$
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define M 8010
using namespace std;
int n,m,p[M],t[M],L[M],R[M]; char s1[M],s2[M];
int pre[M],suf[M],ls[M],rs[M],ct1,ct2,ans;
bool cmp(int x,int y){return L[x]>L[y]||(L[x]==L[y]&&R[x]<R[y]);}
void upd(int tar,int hd,int rev,int con){
if(tar>=hd) ans=min(ans,rev*2+tar+con);
else ans=min(ans,rev*2+(hd*2-tar)+con);
}
int main(){
scanf("%s%s",s1+1,s2+1),n=strlen(s1+1),ans=n*n;
for(int i=1;i<=n;i++) p[i]=s1[i]-'0',t[i]=t[i+n]=t[i+n+n]=s2[i]-'0';
for(int i=1;i<=n;i++) ct1+=p[i],ct2+=t[i];
if(!ct2){puts(ct1?"-1":"0");return 0;}
for(int i=1;i<=n+n;i++) if(!t[i]) ls[i]=(ls[i-1]+1);
for(int i=n+n+n;i>n;i--) if(!t[i]) rs[i]=(rs[i+1]+1);
for(int k=0;k<=n;k++){
m=0,memset(pre,0,sizeof(pre)),memset(suf,0,sizeof(suf));
for(int i=1;i<=n;i++){
if(p[i]^t[i+k]){
m++; if(t[i+k]) continue;
pre[ls[i+n]]=max(pre[ls[i+n]],rs[i+n]);
suf[rs[i+n]]=max(suf[rs[i+n]],ls[i+n]);
}
}
for(int i=n-1;i>=0;i--) suf[i]=max(suf[i],suf[i+1]),pre[i]=max(pre[i],pre[i+1]);
for(int i=0;i<n;i++) upd(k,pre[i+1],i,m),upd(n-k,suf[i+1],i,m);
} printf("%d\n",ans); return 0;
}
Agc019_D Shift and Flip的更多相关文章
- 【agc019D】Shift and Flip
Portal --> agc019D Description 给你一个\(A\)串一个\(B\)串(长度相等的两个\(01\)串),一次操作可以选择将\(A\)向左循环移动一位,将\(A\)向右 ...
- 【AtCoder】AGC019
A - Ice Tea Store 算一下每种零售最少的钱就行,然后优先买2,零头买1 #include <bits/stdc++.h> #define fi first #define ...
- AtCoder练习
1. 3721 Smuggling Marbles 大意: 给定$n+1$节点树, $0$为根节点, 初始在一些节点放一个石子, 然后按顺序进行如下操作. 若$0$节点有石子, 则移入盒子 所有石子移 ...
- POJ 1063 - Flip and Shift
Description This puzzle consists of a random sequence of m black disks and n white disks on an oval- ...
- POJ1063 Flip and Shift
题目来源:http://poj.org/problem?id=1063 题目大意: 有一种游戏如图所示.一个填满黑白球的转盘,它可以有两种操作,一种是将大转盘顺时针旋转,所有球的位置顺时针挪一位,另一 ...
- zoj 1028 Flip and Shift(数学)
Flip and Shift Time Limit: 2 Seconds Memory Limit: 65536 KB This puzzle consists of a random se ...
- POJ 1063 Flip and Shift 最详细的解题报告
题目来源:Flip and Shift 题目大意:一个椭圆形的环形容器中有黑色和白色两种盘子,问你是否可以将黑色的盘子连续的放在一起.你可以有以下两种操作: 1.顺时针旋转所有的盘子 2.顺时针旋转3 ...
- 1254 Flip and Shift
这题是目的是把黑球和白球分开连续放,事实上只要把其中一种颜色分好在一边就可以,可以绕一个球转即是第n个球可以放在n-2或者n+2上,因为这是个环,所以只需要把黑球或者白球连续放好就可以,当一共有奇数个 ...
- shift粘滞键后门创建/复原批处理
创建shift粘滞键后门: 1 c: 2 3 cd \Windows\System32\ 4 5 rename sethc.exe bak_sethc.exe 6 7 xcopy cmd.exe se ...
随机推荐
- C# 关于类型转换 面试题
分别分析一下两种写法是否正确.假设不对.请说明原因 写法一: short s=1; s = s + 1; 写法二: short s=1; s += 1; 解答: 写法一不对,会报出以下的错误: 无法将 ...
- DICOM:C-GET服务
背景: 之前博文对照过多次C-MOVE与C-GET服务的差别,两者最大的差别在于C-GET是基于单个TCP连接的点对点的双方服务.而C-MOVE是基于两个TCP连接的三方服务(详情參见:<DIC ...
- Jmeter + Ant + Jenkins 接口/性能测试,持续集成环境搭建
1. 安装Jmeter.jdk Jmeter 3.3版本 :<http://note.youdao.com/noteshare?id=5e3fd287db24d08386207a7de22d26 ...
- 我的Android进阶之旅------>Android疯狂连连看游戏的实现之加载界面图片和实现游戏Activity(四)
正如在<我的Android进阶之旅------>Android疯狂连连看游戏的实现之状态数据模型(三)>一文中看到的,在AbstractBoard的代码中,当程序需要创建N个Piec ...
- 程序运行之ELF 符号表
当一个工程中有多个文件的时候,链接的本质就是要把多个不同的目标文件相互粘到一起.就想玩具积木一样整合成一个整体.为了使不同的目标文件之间能够相互粘合,这些目标文件之间必须要有固定的规则才行.比如目标文 ...
- 编程算法 - 最好牛线(Best Cow Line) 代码(C)
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u012515223/article/details/37909933 最好牛线(Best Cow L ...
- Mac idea maven 创建web项目
这样项目就创建完成了.然后把Tomcat加入进去就可以跑通了.
- 使VS自动生成代码注释
1.注释模板位置C:\Program Files\Microsoft Visual Studio 11.0\Common7\IDE\ItemTemplatesCache 里面有各种脚本的模板 2.找到 ...
- Kattis - entertainmentbox 【贪心】
思路 先将 N 个 电视节目 排序 根据 结束时间 ,结束的早的 排在前面 然后 弄 K个标记 记录 结束时间 然后 遍历一下 每次 如果能插入的话 插入到 结束时间最小的那个 队列里面去然后 每次插 ...
- python cookbook 迭代器与生成器
代理迭代 a = [1, 2, 3] for i in iter(a): print(i) for i in a.__iter__(): print(i) 这里的两个方法是一样的,调用iter()其实 ...