Portal --> agc019D

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的更多相关文章

  1. 【批处理】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 ...

  2. 【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 ...

  3. 【LeetCode】519. Random Flip Matrix 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址:https://leetcode.com/problems/random-fl ...

  4. 【Atcoder】ARC088 D - Wide Flip

    [题目]D - Wide Flip [题意]给定n个数字的01序列,要求每次翻转>=k个数字使得全0,求最大的k.n<=10^5 [算法]数学 [题解]有两个角度可以得到等价的结论: 1. ...

  5. 181. Flip Bits【easy】

    181. Flip Bits[easy] Determine the number of bits required to flip if you want to convert integer n  ...

  6. 【POJ1753】Flip Game

    [题目大意] 有一个4x4规格的一个棋盘,现在有16个一面黑一面白的棋子分布在这个棋盘上. 翻转一个棋子能够使它以及它上下左右的四个棋子从黑变白,从白变黑. 现在问你至少要经过多少次操作才能够使得整个 ...

  7. 【Atcoder】ARC 080 F - Prime Flip

    [算法]数论,二分图最大匹配 [题意]有无限张牌,给定n张面朝上的牌的坐标(N<=100),其它牌面朝下,每次操作可以选定一个>=3的素数p,并翻转连续p张牌,求最少操作次数使所有牌向下. ...

  8. 企业IT管理员IE11升级指南【17】—— F12 开发者工具

    企业IT管理员IE11升级指南 系列: [1]—— Internet Explorer 11增强保护模式 (EPM) 介绍 [2]—— Internet Explorer 11 对Adobe Flas ...

  9. 【四】搭建Markdown的编辑器

    本系列有五篇:分别是 [一]Ubuntu14.04+Jekyll+Github Pages搭建静态博客:主要是安装方面 [二]jekyll 的使用 :主要是jekyll的配置 [三]Markdown+ ...

随机推荐

  1. Codeblocks自动代码格式化快捷键(自带)

    代码区域右击 点format use AStyle 估计也就是考试竞赛逼着用这个

  2. 01-numpy基础简介

    import numpy as np # ndarray ''' # 三种创建方式 1.从python的基础数据对象转化 2.通过numpy内置的函数生成 3.从硬盘(文件)读取数据 ''' # 创建 ...

  3. halt命令详解

    基础命令学习目录首页 原文链接:https://www.jb51.net/LINUXjishu/57947.html 名称:halt 使用权限:系统管理者 halt 使用方式:halt [-n] [- ...

  4. mongodb基本使用(一)

    1.启动.停止和重启mongodb服务 brew services start mongodb  ---启动 brew services stop mongodb --停止 brew services ...

  5. python实现将json数据以json格式写入txt文件

    json.dumps中indent参数是设置json缩进量的 举例: tmp = { "aaa" : "111", "bbb" : '222 ...

  6. xml配置文件特殊符号的处理方法

    2017.7.19遇到问题:偶然出现“认证失败,请重新登录”的现象   在xml中英文问号“?”是可以被正常解析的,但是以下这几种符号是不能正常解析的:分别是“&”.“<”.“>” ...

  7. to_char

    to_date(to_char(to_date(#{conds.currentTime,jdbcType=VARCHAR},'YYYY-MM-DD hh24:mi:ss'),'hh24:mi:ss') ...

  8. linux 常用命令-配置登陆方式

    使用阿里云服务器,启动实例(ubuntu 7.4,密码登录)后,通过xshell登陆,但是发现xshell中密码登录是灰色禁用的,很惆怅啊,明明设置的就是密码登录,在xshell中找了一通设置发现并没 ...

  9. bug排查

    有时候让朋友,或者群友,或者同事帮忙看一样困扰你很久的bug会得到意向不到的结果. 因为他们往往不像你,已经在调试代码的过程中被一些东西给束缚了.他们会凭借自己的第一直觉来尝试解决问题,跳过你已经走的 ...

  10. 牛客网国庆集训派对Day4题目 2018年

    链接:https://www.nowcoder.com/acm/contest/204/A来源:牛客网 深度学习 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 1048576K,其他 ...