【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+ ...
随机推荐
- python之multiprocessing创建进程
python的multiprocessing模块是用来创建多进程的,下面对multiprocessing总结一下使用记录. multiprocessing创建多进程在windows和linux系统下的 ...
- fetch err : "Body not allowed for GET or HEAD requests"
在使用 fetch 的时候 报了 "Body not allowed for GET or HEAD requests" 这个错. 代码如下: 一番google , 找到答案了. ...
- java代码生成xml 报错:HIERARCHY_REQUEST_ERR: 尝试在不允许的位置插入节点。
document.appendChild(controlElement)好像只能append一个根节点
- bing词典vs有道词典对比测试报告——功能篇之细节与用户体验
之所以将细节与用户体验放在一起讨论,是因为两者是那么的密不可分.所谓“细节决定成败”,在细节上让用户感受方便.舒适.不费心而且温馨,多一些人文理念,多一些情怀,做出来的产品自然比其他呆板的产品更受欢迎 ...
- OO学习体会与阶段总结(设计与实现)
前言 在最近的一个月的课程中,笔者对于规格化编程进行了深入的学习.运用面向对象抽象思想对编写的程序进行过程抽象.异常处理.数据抽象.类的层次规格与迭代等等规格设计,使得程序结构化程度提高,具有更好 ...
- OO的第一次死亡
久仰OO大名,总是想着提前做点准备,其实到头来还是什么准备都没有做,所以这学期就是从零开始的面向对象生活,也因此遇到了很多的问题. 第一次作业——多项式加减 第一次作业历来是较为简单的,但是对于面向对 ...
- 20172321 2017-2018-2 《Java程序设计》第二周学习总结
20172321 2017-2018-2 <Java程序设计>第二周学习总结 教材学习内容总结 第一章要点: 要点1 字符串:print和println用法的区别,字符串的拼接,java中 ...
- linshi18
#include<iostream> using namespace std; int n,m,k; #define max 100 char mmap[max][max]; int mm ...
- 经验分享(Android开发)
以前对于Android开发一点了解都没有,当然,以前觉得是一件很高大上的事情,而且是我没有能力去做的工作,但是在这个小组合作开发Android后,我觉得我有了很大的进步,当然我的进步也是Android ...
- json反序列化对象
这个是同事研究的wcf中中根据type类型反序列化json的示例 /// <summary> /// json转对象 /// </summary> /// <param ...