CF873D Merge Sort
其实最优的方法其他的题解已经讲得很好了,本题解仅用于记录和分享一个新的思路。
这道题是让你输出符合条件的序列,而序列的每个数之间具有一定的逻辑关系,很容易想到拓扑排序,于是此题就变为,如何找出满足条件的逻辑关系。
我们可以先看一下操作次数最多的序列:

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

我们可以通过在\(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的更多相关文章
- [算法]——归并排序(Merge Sort)
归并排序(Merge Sort)与快速排序思想类似:将待排序数据分成两部分,继续将两个子部分进行递归的归并排序:然后将已经有序的两个子部分进行合并,最终完成排序.其时间复杂度与快速排序均为O(nlog ...
- SQL Tuning 基础概述06 - 表的关联方式:Nested Loops Join,Merge Sort Join & Hash Join
nested loops join(嵌套循环) 驱动表返回几条结果集,被驱动表访问多少次,有驱动顺序,无须排序,无任何限制. 驱动表限制条件有索引,被驱动表连接条件有索引. hints:use_n ...
- 归并排序(Merge Sort)
归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列:即先使每个子序列有序,再使子序 ...
- 归并排序(merge sort)
M erge sort is based on the divide-and-conquer paradigm. Its worst-case running time has a lower ord ...
- Summary: Merge Sort of Array && 求逆序对
常用算法(后面有inplace版本): package ArrayMergeSort; import java.util.Arrays; public class Solution { public ...
- 基础排序算法之并归排序(Merge Sort)
并归排序是学习分治法 (Merge Sort) 的好例子.而且它相对于选择,插入,冒泡排序来说,算法性能有一定提升.我首先会描述要解决的问题,并给出一个并归排序的例子.之后是算法的思路以及给出伪代码. ...
- Divide and Conquer.(Merge Sort) by sixleaves
algo-C1-Introductionhtml, body {overflow-x: initial !important;}html { font-size: 14px; }body { marg ...
- STL 源代码剖析 算法 stl_algo.h -- merge sort
本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie merge sort ----------------------------------- ...
- Sort list by merge sort
使用归并排序对链表进行排序 O(nlgn) 的时间效率 /** * Definition for singly-linked list. * struct ListNode { * int val; ...
随机推荐
- python 迭代器(转)
迭代器 迭代器是在python2.2中被加入的,它为类序列对象提供了一个类序列的接口.有了迭代器可以迭代一个不是序列的对象,因为他表现出了序列的行为.当在python中使用for循环迭代一个对象时,调 ...
- 痞子衡嵌入式:JLink Script文件基础及其在IAR下调用方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是JLink Script文件基础及其在IAR下调用方法. JLink可以说是MCU开发者最熟悉的调试工具了,相比于其他调试器(比如DAP ...
- Python_教程_使用Visual Studio Code开发Django项目
如何获得 Visual Studio Code 访问 http://code.visualstudio.com 下载并安装. 前提条件 安装Python 2.7 及 Python 3.5,Window ...
- Java 用jxl读取excel并保存到数据库(此方法存在局限,仅限本地电脑操作,放在服务器上的项目,需要把文件上传到服务器,详细信息,见我的别的博客)
项目中涉及到读取excel中的数据,保存到数据库中,用jxl做起来比较简单. 基本的思路: 把excel放到固定盘里,然后前段页面选择文件,把文件的名字传到后台,再利用jxl进行数据读取,把读取到的数 ...
- SMBv3远程代码执行漏洞复现(CVE-2020-0796)
漏洞基本信息 服务器消息块(SMB),是一个网络通信协议,用于提供共享访问到文件,打印机和串行端口的节点之间的网络上.它还提供了经过身份验证的进程间通信机制.SMB的大多数用法涉及运行Microsof ...
- Guitar Pro使用技巧之乐段回放练习
Guitar Pro中的"回放"功能是我们在吉他练习中非常常用的一项功能.我们在吉他练习中碰到某一乐段比较练习比较困难时,我们就可以用鼠标在Guitar Pro上选中该乐段,然后进 ...
- Javascript 严格模式的一些理解
平常我们在ECMAscript5中可以声明以下的变量 num = 5; console.log(num);//输出的是变量5 而为了Javascript更合理.更安全.更严谨的方向发展,添加了一种新的 ...
- Matlab 画图1
plot函数 plot最简单的是plot(x,y),其中,x,y是一组数据 如果要画出\(y=x^2\)的图像 在Command Window中输入 x =[1 2 3]; y =[4 5 6]; p ...
- redis面试问题(二)
1.redis和其他缓存相比有哪些优点呢 见上一篇 2. 你刚刚提到了持久化,能重点介绍一下么 见上一篇 3.Redis中对于IO的控制做过什么优化? pipeline? 4 有没有尝试进行多机red ...
- 抖音短视频爆火的背后到底是什么——如何快速的开发一个完整的直播app
前言 今年移动直播行业的兴起,诞生了一大批网红,甚至明星也开始直播了,因此不得不跟上时代的步伐,由于第一次接触的原因,因此花了很多时间了解直播,今天我来教你从零开始搭建一个完整的直播app,希望能帮助 ...