题目

似乎很久没写题解了...

这题是校里胡策的时候的题,比赛因为评测机有点慢+自己代码常数大没快读...被卡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补满

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define maxn 200050
 4 using namespace std;
 5 int n;
 6 int v[maxn],now[maxn];
 7 int a[maxn],b[maxn],x[maxn*3],y[maxn*3];
 8 struct qnode{
 9     int x,y;
10 }q[maxn*3];
11 int check(int m){
12     for (int i=0;i<n;i++)
13     b[i]=a[i],v[i]=0;
14     for (int i=1;i<=m;i++)
15     swap(b[x[i]],b[y[i]]);
16     int need=0;
17     for (int i=0;i<n;i++)
18     if (!v[i]){
19         int x=i;
20         while (!v[x]){
21             v[x]=1;
22             if (!v[b[x]]) {
23                 q[++need].x=b[x];
24                 q[need].y=b[b[x]];
25             }
26             x=b[x];
27         }
28     }
29     return need;
30 }
31 int main(){
32 //    freopen("game.in","r",stdin);
33 //    freopen("game.out","w",stdout);
34     scanf("%d",&n);
35     for (int i=0;i<n;i++)
36     scanf("%d",&a[i]),now[a[i]]=i;
37     int Q;
38     scanf("%d",&Q);
39     for (int i=1;i<=Q;i++)
40     scanf("%d%d",&x[i],&y[i]);
41     int l=0,r=Q;
42     while (l<=r){
43         int m=(l+r)>>1;
44         if (check(m)>m) l=m+1;else r=m-1;
45     }
46     int need=check(l);
47     printf("%d\n",l);
48     for (int i=1;i<=need;i++){
49         swap(a[x[i]],a[y[i]]);
50         now[a[x[i]]]=x[i];
51         now[a[y[i]]]=y[i];
52         printf("%d %d\n",now[q[i].x],now[q[i].y]);
53         swap(a[now[q[i].x]],a[now[q[i].y]]);
54         now[a[now[q[i].x]]]=now[q[i].x];
55         now[a[now[q[i].y]]]=now[q[i].y];
56     }
57     for (int i=need+1;i<=l;i++)
58     printf("0 0\n");
59     return 0;
60 }

4371

转载于:https://www.cnblogs.com/Bunnycxk/p/10692340.html

Bzoj 4371: [IOI2015]sorting排序 二分相关推荐

  1. Sorting 排序详解(c语言实现)

    Sorting 排序详解(c语言实现)# 今日突然有任务,明天补充完整. 邮箱:Is_Dmy@163.com期待交流. Hello,各位小伙伴~我是你们的课代表橙橙,今天呢我要给大家分享的是关于内排序 ...

  2. 51Nod-1090 3个数和为0【排序+二分查找】

    1090 3个数和为0 基准时间限制:1秒 空间限制:131072KB 分值:5难度:1级算法题 给出一个长度为N的无序数组,数组中的元素为整数,有正有负包括0,并互不相等.从中找出所有和 = 0的3 ...

  3. 【splay】BZOJ 1152 3506:[cqoi2014]排序机械臂

    BZOJ 1152 && 3506:[cqoi2014]排序机械臂 Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,第二行为N个用空格隔开的正整数 ...

  4. BZOJ.4552.[HEOI2016/TJOI2016]排序(线段树合并/二分 线段树)

    题目链接 对于序列上每一段连续区间的数我们都可以动态开点建一棵值域线段树.初始时就是\(n\)棵. 对于每次操作,我们可以将\([l,r]\)的数分别从之前它所属的若干段区间中分离出来,合并. 对于升 ...

  5. BZOJ.2161. 布娃娃【整体二分】

    传送门 NNN 个区间记为 [l,r][l,r][l,r]形式,魅力值,记为CiC_iCi​形式 NNN 个耐力值,记为 PiP_iPi​形式 求覆盖PiP_iPi​的区间内,魅力值第iii大是多少 ...

  6. 线段树分裂与合并 ----- P2824 [HEOI2016/TJOI2016]排序 [线段树分裂合并 OR 01序列排序+二分线段树]

    题目链接 题目大意: 对一个序列,每次按照升序或者降序排序序列某一段,问你最后的序列是什么? 解法1:二分+线段树 首先我们知道对一个01序列进行排序是很快的!我们只要知道里面有多少个1和多少个0,那 ...

  7. [排序][二分][dp]JZOJ 2747 捡金子

    Description 从前有一个迷宫,迷宫的外形就像一棵带根树,每个结点(除了叶子结点外)恰好有K个儿子. 一开始你在根结点,根结点的K个儿子分别标记为'A', 'B', 'C'-.,而结点'A'的 ...

  8. [蓝桥杯][2015年第六届真题]密文搜索(排序+二分)

    题目描述 福尔摩斯从X星收到一份资料,全部是小写字母组成. 他的助手提供了另一份资料:许多长度为8的密码列表. 福尔摩斯发现,这些密码是被打乱后隐藏在先前那份资料中的. 请你编写一个程序,从第一份资料 ...

  9. P3573-[POI2014]RAJ-Rally【拓扑排序,二分+树状数组】

    正题 题目链接:https://www.luogu.com.cn/problem/P3573 题目大意 nnn个点mmm条边的DAGDAGDAG,删掉一个点使得最长路最短. 解题思路 先跑一遍拓扑排序 ...

最新文章

  1. 面试题:函数回调机制、异步函数回调机制图例详解 没毛用
  2. 多校第六场 HDU 4927 JAVA大数类+模拟
  3. qt设置模态对话框并设置对话框的位置
  4. hibernate简单应用
  5. matlab2c使用c++实现matlab函数系列教程-triu函数
  6. 北航机械学院计算机制图,北航机械制图在线作业一含答案.pdf
  7. PostgreSQL 10.1 手册_部分 I. 教程
  8. 基于python的计算基因组_【ROSALIND】【练Python,学生信】05 计算DNA序列GC含量
  9. java+sql+用户登录失败,java.sql.SQLException:用户'sa'登录失败
  10. 甲基化芯片Beta值意义详解,以及minfi包使用
  11. Vue.js---关闭语法检查
  12. excel数据透视表_Excel数据透视表在奥运会上
  13. 提问:usb摄像头无输出画面 /window下能识别摄像头,无输出图像拍摄时提示0XA00F4292(PhotoCaptureStartTimeout) /linux下不能识别
  14. 2015合肥市第 32 届青少年信息学(计算机)奥林匹克竞赛小学组试题
  15. VS2019不能安装的WIN10更新问题
  16. 移动硬盘加密方法加密后对硬盘读写的影响
  17. python中经常使用的包扎材料_以下哪些是经常使用的包扎材料:
  18. 西邮Linux兴趣小组纳新笔试试题
  19. SSM项目 “信息发送” 详细步骤
  20. 开源知识库存储管理平台

热门文章

  1. [原][osgearth]osgearthElvation中的一帧
  2. 2015年传智播客JavaEE 第168期就业班视频教程day38-SSH综合案例-1
  3. 关于事件模型,js事件绑定和解除的学习
  4. JavaEE基础(三)
  5. neo4j-访问提示No authorization header supplied.
  6. LeetCode(557)——反转字符串中的单词 III(JavaScript)
  7. 解决Vscode提示bodyparser已被弃用的问题
  8. 【ECharts学习】—实现我的第一个图表
  9. CentOS系统安装Java
  10. 转专业有什么要求吗?