其实最优的方法其他的题解已经讲得很好了,本题解仅用于记录和分享一个新的思路。


这道题是让你输出符合条件的序列,而序列的每个数之间具有一定的逻辑关系,很容易想到拓扑排序,于是此题就变为,如何找出满足条件的逻辑关系。

我们可以先看一下操作次数最多的序列:

(每一条红线都是一次操作),我们可以删除一次操作,当且仅当左半边与右半边都排好序的情况下,即删除了所有子操作的情况下,使得左半边与右半边中间建一条边,如图:

我们可以通过在\(1\)与\(2\)之间建一条边来删除\(1\)与\(2\)两者的操作

我们还可以通过在\(2\)与\(3\)之间建一条边来删除\(1\)与\(2\)之间,\(3\)与\(4\)之间的操作,但此时\(1\)与\(2\),\(3\)与\(4\)之间必须已经建边

上述操作可以通过递归完成,最后再跑一边拓扑排序,复杂度\(O(nlogn)\)

#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
int n,k;
struct Edge
{
int to,nxt;
}e[100005];
int fir[100005],size;
int d[100005];
void add(int u,int v)
{
e[++size].to=v;
e[size].nxt=fir[u];
fir[u]=size;
++d[v];
}
int cnt;
void merge(int l,int r)
{
if(l==r-1)
{
return ;
}
int mid=(l+r)/2;
merge(l,mid);
merge(mid,r);
if(cnt>k)
{
add(mid-1,mid);
cnt-=2;
}
}
queue <int> q;
int ans[100005];
void top()
{
for(int i=n-1;i>=0;--i)
{
if(d[i]==0)
q.push(i);
}//一定要反向塞入,拓扑排序仅能保证逻辑关系,本题顺序非正即反,所以未建边的位置就是反的
cnt=0;
while(q.size())
{
int tmp=q.front();
q.pop();
ans[tmp+1]=++cnt;//我们建边和拓扑的是点的位置,根据出队顺序决定数字顺序
for(int i=fir[tmp];i;i=e[i].nxt)
{
--d[e[i].to];
if(d[e[i].to]==0)
q.push(e[i].to);
}
}
}
int main()
{
cin>>n>>k;
if(k%2==0||k>2*n-1)
{
printf("-1\n");
return 0;
}
cnt=2*n-1;
merge(0,n);
top();
for(int i=1;i<=n;++i)
{
printf("%d ",ans[i]);
}
printf("\n");
return 0;
}

CF873D Merge Sort的更多相关文章

  1. [算法]——归并排序(Merge Sort)

    归并排序(Merge Sort)与快速排序思想类似:将待排序数据分成两部分,继续将两个子部分进行递归的归并排序:然后将已经有序的两个子部分进行合并,最终完成排序.其时间复杂度与快速排序均为O(nlog ...

  2. SQL Tuning 基础概述06 - 表的关联方式:Nested Loops Join,Merge Sort Join & Hash Join

    nested loops join(嵌套循环)   驱动表返回几条结果集,被驱动表访问多少次,有驱动顺序,无须排序,无任何限制. 驱动表限制条件有索引,被驱动表连接条件有索引. hints:use_n ...

  3. 归并排序(Merge Sort)

    归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列:即先使每个子序列有序,再使子序 ...

  4. 归并排序(merge sort)

    M erge sort is based on the divide-and-conquer paradigm. Its worst-case running time has a lower ord ...

  5. Summary: Merge Sort of Array && 求逆序对

    常用算法(后面有inplace版本): package ArrayMergeSort; import java.util.Arrays; public class Solution { public ...

  6. 基础排序算法之并归排序(Merge Sort)

    并归排序是学习分治法 (Merge Sort) 的好例子.而且它相对于选择,插入,冒泡排序来说,算法性能有一定提升.我首先会描述要解决的问题,并给出一个并归排序的例子.之后是算法的思路以及给出伪代码. ...

  7. Divide and Conquer.(Merge Sort) by sixleaves

    algo-C1-Introductionhtml, body {overflow-x: initial !important;}html { font-size: 14px; }body { marg ...

  8. STL 源代码剖析 算法 stl_algo.h -- merge sort

    本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie merge sort ----------------------------------- ...

  9. Sort list by merge sort

    使用归并排序对链表进行排序 O(nlgn) 的时间效率 /** * Definition for singly-linked list. * struct ListNode { * int val; ...

随机推荐

  1. 03 原型模式(prototype)

    03 原型模式(prototype) 1 克隆羊问题 现在有一只羊tom,姓名为: tom.年龄为: 1,颜色为:白色,请编写程序创建和tom羊属性完全相同的10只羊. 2 传统方式解决 思路 cla ...

  2. SQL SERVER中 DBLINK的实现

    不同服务器数据库之间的数据操作 --创建链接服务器 exec sp_addlinkedserver'ITSV' ,'' , 'SQLOLEDB' ,'远程服务器名或ip地址' exec sp_addl ...

  3. Oracle 集合类型

    集合类型 1. 使用条件: a. 单行单列的数据,使用标量变量 .    b. 单行多列数据,使用记录 [ 详细讲解请见: 点击打开链接 ]   c. 单列多行数据,使用集合 *集合:类似于编程语言中 ...

  4. 冷门的HTML - tabindex 的作用

    冷门的HTML - tabindex 的作用 HTML 的 tabindex 属性开发过程中一般不会使用到,最近开发中有个需求兼顾富交互,便总结了一下.本篇文章同时收录在我的[前端知识点]中,Gith ...

  5. 光棍节程序员闯关秀writeup

    答题链接https://1111.segmentfault.com/ 第一关 首先当然是右键查看源码啊 点击链接进入下一关 第二关 还是老样子,右键查看源码 这个key是要放在URL链接里敲回车的 第 ...

  6. 企业级工作流解决方案(九)--微服务Tcp消息传输模型之客户端处理

    客户端启动 客户端启动主要做三件事情,1. 从配置文件读取服务调用配置,存储到全局对象中.2. 指定客户端编解码器工厂.3. 预连接,即预先建立与服务端的通信Chanel. [DependsOn(ty ...

  7. 全面解析RayFire的动态对象与静态对象

    我们在日常使用RayFire的过程中,接触得比较多的应该就是RayFire的对象设置了.RayFire的对象包含了动态对象.静态对象与休眠对象,其中动态对象.静态对象可以结合动力学.运动学概念设置动作 ...

  8. ubuntu安装php的 redis扩展

    wget https://github.com/phpredis/phpredis/archive/2.2.4.tar.gztar -zxvf 2.2.4.tar.gz cd phpredis-2.2 ...

  9. Redis 基础数据结构之一:string(字符串)

    Redis 有 5 种基础数据结构,分别为:string (字符串).list (列表).set (集合).hash (哈希) 和 zset (有序集合),Redis存储数据的结构是键值对形式的. 首 ...

  10. Java基础教程——Stream

    Stream流 Java 8 API添加了一种新的机制--Stream(流).Stream和IO流不是一回事. 流式思想:像生产流水线一样,一个操作接一个操作. 使用Stream流的步骤:数据源→转换 ...