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. 图-最小生成树算法之Kruskal及其Java实现

    1.Kruskal算法 Kruskal算法基于贪心,因此它追求的是近似最优解,也就是说由Kruskal得出的生成树并不一定是最优解. Kruskal算法求最小生成树的关键在于,每次选取图中权值最小(及 ...

  2. Django缓存配置和使用

    - 缓存 - 配置 CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', 'LOCAT ...

  3. AutoResetEvent 方法名称设计缺陷

    这个类和方法,让人乍一读是读不明白的.不能通过方法名称明白其含义.所以它的方法名称设计是欠考虑. 应该类似于这样: public static class MyAutoResetEvent { pub ...

  4. mkdir命令详情

    基础命令学习目录首页 原文链接:https://blog.csdn.net/zwlove5280/article/details/74618041 mkdir 是创建目录的命令. 创建一级目录 mkd ...

  5. rest_framework_api规范

    目录 一.什么是RESTful 二.什么是API 三.RESTful API规范 四.基于Django实现API 五.基于Django Rest Framework框架实现 一. 什么是RESTful ...

  6. JSBridge的原理

    前言 参考来源 前人栽树,后台乘凉,本文参考了以下来源 github-WebViewJavascriptBridge JSBridge-Web与Native交互之iOS篇 Ios Android Hy ...

  7. 实验三 Java猜数字游戏开发

    课程:Java实验   班级:201352     姓名:程涵  学号:20135210 成绩:             指导教师:娄佳鹏   实验日期:15.06.03 实验密级:         ...

  8. cnblogs用户体验评价

    1. 是否提供良好的体验给用户(同时提供价值)? 博客园就相当于现在生活中处处可见的微博,所有人都在上面发表自己的一些看法,当然我们比较关注的是计算机编程方面的一些博客,大多数编程人员愿意分享自己的代 ...

  9. 场景调研 persona

    1.姓名:王涛 2.年龄:22 3.收入:基本无收入 4.代表用户在市场上的比例和重要性:王涛为铁道学生.本软件的用户主要是学生和老师,尤其是广大的铁大学子,所以此典型用户的重要性不言而喻,而且比例相 ...

  10. 第三次作业— C++计算器项目的初始部分

    作业题目: C++计算器项目的初始部分 仓库 代码: Scan.h #ifndef SCAN_H #define SCAN_H #include<string> #include<i ...