Bzoj 4371: [IOI2015]sorting排序 二分
似乎很久没写题解了...
这题是校里胡策的时候的题,比赛因为评测机有点慢+自己代码常数大没快读...被卡t了,但是bzoj上还是A了的...,因为bzoj时限比较宽可以不卡常。
题解:
首先可以发现答案与操作顺序是无关的,也就是说,可以钦定答案就是x次操作,然后让先手的x次先全换了,然后再考虑我要怎么换,才能在最少次数内换成升序。
于是就可以直接枚举答案x,然后判一下x是否可行。
考虑如何判断,问题会变成,给定一个a序列,每次可以交换两个数,问最少交换多少次可以换成升序,也就是变成a[i]=i。
这是一个经典问题,考虑 i 必须换到 a[i] 的位置,于是就直接一直跳就好了,最后会变成若干个环。
一个环中如果有n个数,那么必须需要也只需要 n-1 次就可以换成 a[i]=i 的情况。
因此最少的交换次数就是每个环大小-1加起来,可以在 O(n) 的时间复杂度下完成判断。
那么枚举答案+判断答案是 O(n^2) 的,没得聊。
其实答案是可以二分的,满足二分性质。
证明:即证明如果答案为x可行,那么答案为x+1也必然可行,如果x可行,那么我花x次操作变成升序,然后第x+1次操作,先手怎么换,我就再换回去,序列依旧是升序的。
那么效率就是 O(nlogn) 的
虽然答案与顺序无关,但是操作方案是和顺序有关的。
转换一下思路,交换两个数,可以理解成两个位置交换,但是其实也可以理解成两个数字交换。
而位置和顺序有关,因为先手换完之后我本来想换的位置就会变了。
但是数字和顺序是没关系的,所以我记录一下我环中交换的那些数。
然后按题意模拟,每次维护一下now[i]表示 i 这个数现在的位置,于是就变得很简单了...
注意一下两个人都操作一次才算完,不能先手操作完后是升序的我就不操作了。
所以如果可以不操作的,要拿 0 0补满
#include<cstdio>
#include<algorithm>
#define maxn 200050
using namespace std;
int n;
int v[maxn],now[maxn];
int a[maxn],b[maxn],x[maxn*],y[maxn*];
struct qnode{
int x,y;
}q[maxn*];
int check(int m){
for (int i=;i<n;i++)
b[i]=a[i],v[i]=;
for (int i=;i<=m;i++)
swap(b[x[i]],b[y[i]]);
int need=;
for (int i=;i<n;i++)
if (!v[i]){
int x=i;
while (!v[x]){
v[x]=;
if (!v[b[x]]) {
q[++need].x=b[x];
q[need].y=b[b[x]];
}
x=b[x];
}
}
return need;
}
int main(){
// freopen("game.in","r",stdin);
// freopen("game.out","w",stdout);
scanf("%d",&n);
for (int i=;i<n;i++)
scanf("%d",&a[i]),now[a[i]]=i;
int Q;
scanf("%d",&Q);
for (int i=;i<=Q;i++)
scanf("%d%d",&x[i],&y[i]);
int l=,r=Q;
while (l<=r){
int m=(l+r)>>;
if (check(m)>m) l=m+;else r=m-;
}
int need=check(l);
printf("%d\n",l);
for (int i=;i<=need;i++){
swap(a[x[i]],a[y[i]]);
now[a[x[i]]]=x[i];
now[a[y[i]]]=y[i];
printf("%d %d\n",now[q[i].x],now[q[i].y]);
swap(a[now[q[i].x]],a[now[q[i].y]]);
now[a[now[q[i].x]]]=now[q[i].x];
now[a[now[q[i].y]]]=now[q[i].y];
}
for (int i=need+;i<=l;i++)
printf("0 0\n");
return ;
}
4371
Bzoj 4371: [IOI2015]sorting排序 二分的更多相关文章
- bzoj 4552 [Tjoi2016&Heoi2016]排序 (二分答案 线段树)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4552 题意: 给你一个1-n的全排列,m次操作,操作由两种:1.将[l,r]升序排序,2 ...
- BZOJ 4552 [Tjoi2016&Heoi2016]排序 | 二分答案 线段树
题目链接 题面 题目描述 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这 ...
- bzoj 4552 [Tjoi2016&Heoi2016]排序——二分答案
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4552 二分答案,把 >= mid 的设成1.< mid 的设成0,之后排序就变成 ...
- bzoj 4552: [Tjoi2016&Heoi2016]排序——二分+线段树
Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这 ...
- UVA.10474 Where is the Marble ( 排序 二分查找 )
UVA.10474 Where is the Marble ( 排序 二分查找 ) 题意分析 大水题一道.排序好找到第一个目标数字的位置,返回其下标即可.暴力可过,强行写了一发BS,发现错误百出.应了 ...
- bzoj 4552: [Tjoi2016&Heoi2016]排序【二分+线段树】
二分值mid,然后把>=mid的赋值为1,其他赋值为0,每次排序就是算出区间内01的个数,然后分别把0和1放到连续的一段内,这些都可以用线段树来维护 二分的判断条件是操作完之后q位置上是否为1 ...
- BZOJ 4552: [Tjoi2016&Heoi2016]排序 线段树 二分
目录 此代码是个假代码,只能糊弄luogu,以后再改,路过大佬也可以帮一下辣 update 10.6 此代码是个假代码,只能糊弄luogu,以后再改,路过大佬也可以帮一下辣 /* //fang zhi ...
- BZOJ.4552.[HEOI2016/TJOI2016]排序(线段树合并/二分 线段树)
题目链接 对于序列上每一段连续区间的数我们都可以动态开点建一棵值域线段树.初始时就是\(n\)棵. 对于每次操作,我们可以将\([l,r]\)的数分别从之前它所属的若干段区间中分离出来,合并. 对于升 ...
- BZOJ 4552 [Tjoi2016&Heoi2016]排序 ——线段树 二分答案
听说是BC原题. 好题,二分答案变成01序列,就可以方便的用线段树维护了. 然后就是区间查询和覆盖了. #include <map> #include <cmath> #inc ...
随机推荐
- Eclipse 真机调试检测不到手机解决方案
想用Eclipse真机调试,但是死活检测不到手机. 手机已经打开了usb调试模式. 开始用的华为Mate9,后面试了下小米,都不行. 在网上搜了一堆,什么安全驱动.adb占用.删除360手机助手.修改 ...
- 【BZOJ3529】[Sdoi2014]数表 莫比乌斯反演+树状数组
[BZOJ3529][Sdoi2014]数表 Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和 ...
- Git的配置和使用
eclipse中Git的配置 可以参考http://www.cnblogs.com/zhxiaomiao/archive/2013/05/16/3081148.html, http://blog.cs ...
- ionic开发过程中遇到的一些坑!
总结一些:在使用 ionic 开发过程中所遇到的问题. 问题一:Cannot find module '@ionic/app-scripts' 描述:使用 ionic start 项目的时候,项目安装 ...
- ssh-keygen 不是内部或外部命令解决办法!
在使用 git 的远程仓库的时候,生成秘钥的使用,会遇到ssh-keygen不是内部命令也不是外部命令的问题: 具体解决: 第一步:找到:Git/usr/bin目录下的ssh-keygen.exe(一 ...
- 最小树形图(hdu4009)
Transfer water Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others) T ...
- 【巷子】---vue路由懒加载---【vue】
一.懒加载 也叫延迟加载或者按需加载,即在需要的时候进行加载, 二.为什么要使用懒加载 像vue这种单页面应用,如果没有应用懒加载,运用webpack打包后的文件将会异常的大,造成进入首页时,需要 ...
- 【事件流】浅谈事件冒泡&&事件捕获------【巷子】
首先在扯淡的时候我们需要先了解一个东西,这个东西就是事件流. 1.什么是事件流? 解释:当一个HTML元素触发一个事件处理函数的时候,该事件会在该元素节点到根节点之间传播,传播路径所经过的节点都会接受 ...
- 170703、springboot编程之模板使用(thymeleaf、freemarker)
官方不推荐集成jsp,关于使用jsp模板我这里就不赘述,如果有需要的,请自行百度! thymeleaf的使用 1.在pom中增加thymeleaf支持 <dependency> <g ...
- 安卓中通知(Notification)的基本使用方法
1. 通知的使用场合 当某个应用程序希望向用户发出一些提示信息,而该应用程序又不在前台运行时,就可以借助通知来实现.发出一条通知后,手机最上方的状态栏中会显示一个通知的图标,下拉状态栏后可以看到通知的 ...