【agc019D】Shift and Flip
Description
给你一个\(A\)串一个\(B\)串(长度相等的两个\(01\)串),一次操作可以选择将\(A\)向左循环移动一位,将\(A\)向右循环移动一位,或者选择某个满足\(B_i=1\)的\(i\),将\(A_i\)反转(\(0\)变\(1\),\(1\)变\(0\))
目标是让两个串相等,求最小的操作次数,无解就\(-1\)
Solution
首先判掉不需要操作的情况:如果两个串一开始就相等了就不用操作了
然后再判掉无解的情况:如果这个时候\(B\)串中没有\(1\)那么当然不用玩了
只要\(B\)中有\(1\)一定有解,因为实在不行你可以把每一个要变的位置都先转到那里去然后反转一下再转回来
那么现在。。来看怎么计算最小操作数(其实想法很暴力==)
首先我们要解决一个问题:最后\(A\)的每一位对的是\(B\)的哪一位(也就是那个下标的偏移量具体是多少),既然长度只有\(2000\)那当然是枚举啊(什么玩意==)
假设最后的偏移量是\(mv\),那么再怎么样我们肯定要把\(A\)转到那个位置去,所以如果说这转的中途有需要反转的位置可以对上一个\(1\)的话,就直接反转就好了,同时还有一些位置可能并不能对上一个\(1\),那么这些位置还需要额外往左边或者右边转一段距离反转,然后再转回来
假设我们现在已经知道了所有需要额外往左边或者右边移动的位置,以及他们具体往左边(或右边)移动多少,假设往左边移动最多的是\(mxl\),往右边移动最多的是\(mxr\),那么除去那个必须移动的偏移量以及反转的贡献以外,还需要\(2*(mxl+mxr)\)步,具体的话就是因为。。你要先往左边走\(mxl\)步,然后走偏移量,然后再往右边走\(mxr\)步,完了之后还要走回来
那么现在我们要先出这些位置往左边或右边走到第一个\(1\)所需要的操作数量,这个可以通过预处理得到比较简单就不再赘述
最后的问题就是。。怎么求出最小的\(2*(mxl+mxr)\):假设我们将每个位置往左走往右走的操作数量记成一个数对\((l,r)\),那么我们可以将这些数对先按照\(l\)排序,然后从大到小扫,对于每一个位置,计算当这个位置的\(l\)为\(mxl\)时的\(mxr\)应该是多少(具体就是。。边扫边记录扫过的\(r\)的\(max\)就好了,因为如果当前的位置要是\(mxl\),那么比它\(l\)大的位置只能往右走,而比它\(l\)小的位置怎么走都无所谓但是为了让\(mxr\)尽量小,所以我们当然希望往右走的位置尽量少)
然后。。总的时间复杂度就是\(O(n^2logn)\)了(虽然说里面扫是线性的但是需要排序)
mark:所以其实有些时候需要暴力一点的想法==
代码大概长这个样子
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define mp make_pair
#define Pr pair<int,int>
using namespace std;
const int N=6010,inf=1e9;
vector<Pr> rec;
char A[N],B[N];
int cnt1[N],L[N],R[N];
int n,m,ok,ans;
int Id(int x){return x+n;}
void prework(){
for (int i=1;i<=n;++i){
B[i+n]=B[i+n+n]=B[i];
if (A[i]!=B[i]) ok=false;
}
cnt1[0]=0;
for (int i=1;i<=n*3+1;++i)
cnt1[i]=cnt1[i-1]+(B[i]=='1');
int loc1=-1;
L[0]=-inf;
for (int i=1;i<=3*n;++i) L[i]=B[i]=='1'?i:L[i-1];
R[3*n+1]=inf;
for (int i=3*n;i>=1;--i) R[i]=B[i]=='1'?i:R[i+1];
}
int Abs(int x){return x<0?-x:x;}
void solve(){
if (ok){printf("0\n");return;}
if (cnt1[n]==0){printf("-1\n");return;}
int flip=0,l,r,mxr,tmpans;
ans=inf;
for (int mv=-n;mv<=n;++mv){
rec.clear(); flip=0; rec.push_back(mp(0,0));
for (int i=1;i<=n;++i){
if (A[i]==B[i+Id(mv)]) continue;
++flip;
l=i+Id(mv); r=Id(i);
if (l>r) swap(l,r);
if (cnt1[r]-cnt1[l-1]==0)
rec.push_back(mp(l-L[l],R[r]-r));
}
sort(rec.begin(),rec.end());
mxr=0; tmpans=inf;
for (int i=rec.size()-1;i>=0;--i){
if (rec[i].first!=-inf)
tmpans=min(tmpans,2*(rec[i].first+mxr));
mxr=max(mxr,rec[i].second);
if (mxr==inf) break;
}
if (tmpans!=inf)
ans=min(ans,tmpans+Abs(mv)+flip);
}
printf("%d\n",ans);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
scanf("%s",A+1); n=strlen(A+1);
scanf("%s",B+1); ok=true;
prework();
solve();
}
【agc019D】Shift and Flip的更多相关文章
- 【批处理】shift用法举例
@echo off set sum=0 call :sub sum 1 2 3 4 echo sum=%sum% pause :sub set /a %1=%1+%2 shift /2 if not ...
- 【leetcode】519. Random Flip Matrix
题目如下: You are given the number of rows n_rows and number of columns n_cols of a 2D binary matrix whe ...
- 【LeetCode】519. Random Flip Matrix 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址:https://leetcode.com/problems/random-fl ...
- 【Atcoder】ARC088 D - Wide Flip
[题目]D - Wide Flip [题意]给定n个数字的01序列,要求每次翻转>=k个数字使得全0,求最大的k.n<=10^5 [算法]数学 [题解]有两个角度可以得到等价的结论: 1. ...
- 181. Flip Bits【easy】
181. Flip Bits[easy] Determine the number of bits required to flip if you want to convert integer n ...
- 【POJ1753】Flip Game
[题目大意] 有一个4x4规格的一个棋盘,现在有16个一面黑一面白的棋子分布在这个棋盘上. 翻转一个棋子能够使它以及它上下左右的四个棋子从黑变白,从白变黑. 现在问你至少要经过多少次操作才能够使得整个 ...
- 【Atcoder】ARC 080 F - Prime Flip
[算法]数论,二分图最大匹配 [题意]有无限张牌,给定n张面朝上的牌的坐标(N<=100),其它牌面朝下,每次操作可以选定一个>=3的素数p,并翻转连续p张牌,求最少操作次数使所有牌向下. ...
- 企业IT管理员IE11升级指南【17】—— F12 开发者工具
企业IT管理员IE11升级指南 系列: [1]—— Internet Explorer 11增强保护模式 (EPM) 介绍 [2]—— Internet Explorer 11 对Adobe Flas ...
- 【四】搭建Markdown的编辑器
本系列有五篇:分别是 [一]Ubuntu14.04+Jekyll+Github Pages搭建静态博客:主要是安装方面 [二]jekyll 的使用 :主要是jekyll的配置 [三]Markdown+ ...
随机推荐
- CentOs6.5中安装和配置vsftp简明教程[转]
CentOs6.5中安装和配置vsftp简明教程 林涛 发表于:2017-3-17 10:10 分类:WebServer 标签: 101次 一.vsftp安装篇 复制代码代码如下: # 安装vsftp ...
- No.1_NABCD模型分析
Reminder 之 NABCD模型分析 定位 多平台的闹钟提醒软件. 在安卓市场发布软件,发布后一周的用户量为1000. N (Need 需求) 这个 ...
- 实验五Java网络编程及安全
实验五 Java网络编程及安全 结对伙伴:20135231林涵锦(负责服务器方)http://www.cnblogs.com/20135213lhj/ 实验目的与要求: 1.掌握Java网络编程的方 ...
- 在Windows下制作静态库和动态库
一:静态库的创建 VC++6.0中new一个的为win32 static library工程,之后有二个选项.根据需求选吧. 具体的类或者函数的添加过程和标准的工程一样,直接创建新的类或者添加新 的. ...
- Chapter 6 面向对象基础
面向对象=对象+类+继承+通信,如果一个软件系统采用这些概念来建立模型并给予实现,那么它就是面向对象的.面向对象的软件工程方法是面向对象方法在软件工程领域的全面运用涉及到从面向对象分析.面向对象设计. ...
- 修改MyEclipse工作空间
MyEclipse如何更改工作空间,MyEclipse是java开发常用工具,在开发的过程中我们会经常切换工作空间来切换项目内容,初学者来说有必要讲一下如何切换工作空间 工具/原料 MyEclip ...
- C++自学及C的补缺
我这个寒假可以坐在电脑前的时间算是比较少的,因为我放假不久后就去打工了,而打工的时间是很流动的,所以我无法固定时间来学习,因此我只能根据我的打工时间来安排我的学习. 由于我的书是除夕前夕淘宝的,近期是 ...
- 项目Beta冲刺(团队)第六天
1.昨天的困难 可以获得教务处通知栏的15条文章数据了,但是在显示的时候出了问题. 私信聊天的交互还没研究清楚 2.今天解决的进度 成员 进度 陈家权 研究私信模块 赖晓连 研究问答模块 雷晶 研究服 ...
- 项目Beta冲刺(团队)第三天
1.昨天的困难 记住密码打勾之后点击登录记住密码这四个字会变成省略号 点赞点击以后本应该呈现的爱心形状变成了方块 2.今天解决的进度 成员 进度 陈家权 私信模块探索ing,回复详情界面设计 赖晓连 ...
- Git的基本使用方法和安装&心得体会(使用git命令行)
这是补发的,使用命令行操作的. (1)选择本地repository的路径 找到后点鼠标右键,选择git bash here. (2) clone到本地 在命令行输入 git clone ADDRESS ...