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_图解教程
说明:本教程用图片+源码讲解Python常见的问题,共勉! 1.Python包的调用 # coding:utf8 # from pakge.mymodel import test from bao ...
- Win7 安装 Docker 踩的那些坑
公司电脑是 WIN7 x64 旗舰版 SP1,安装 Docker 时踩了好多雷,分享出来给大家排排雷. 首先,Docker Desktop Installer 的 Windows 版只支持 Win10 ...
- mysql之事物
1.事物,在事物中的sql语句,要么全部执行成功,要么全部执行失败,不会出现一条sql执行成功了,一条sql执行失败的问题. 2.开启事物:就是关闭mysql自己的自动提交事物的方式 3.commit ...
- 讲一讲Java的字符串常量池,看完你的思路就清晰了
前言 很多朋友Java的字符串常量池的概念困扰了很长一段时间,最近研究了一下jvm指令码,终于对它有了大概的了解. 在展示案例前,我们需要先搞清楚一个概念,众所周知,jvm的内存模型由程序计数器.虚拟 ...
- NO.A.0010——Windows常用快捷键使用教程
小娜操作: Win + C: 打开Cortana微软小娜,并开始聆听...... Win + Q: 打开Cortana: Win + S: 打开Cortana:sdfghjkrtgyh XBOX操作: ...
- appium每次运行不初始化
最近测试公司软件遇到一个问题,每次运行Appium测试代码,打开软件都是初始化,每次的新手教程以及无法记住密码一堆问题,导致效率很低,而且定位有时候出问题. 先看初始化的代码 1 from appiu ...
- python3时间函数
上一篇是生成测试报告的代码,如果重复运行测试报告名称相同会不停的覆盖,之前的测试报告也会丢失,无法追溯之前的问题.那么如何解决这个问题了呢? 首先想到的是用随机函数取随机名称,一旦生成的报告较多时,无 ...
- QBXT 提高组储备营 2020.夏 游记
DAY 1 是第一天呐!老师好强!讲得好仔细!连我都全懂了![doge] 突然对后面几天充满了期待-- 复习内容:二分,排序,贪心,搜索(好评) 新知识:Huffman树及Huffman编码,对拍,二 ...
- CodeChef-LECOINS Little Elephant and Colored Coins 题解
CodeChef-LECOINS Little Elephant and Colored Coins Little Elephant and Colored Coins The Little Elep ...
- JavaSE 学习笔记02丨对象与类
Chapter 4. 对象与类 4.1 面向对象程序设计概述 面向对象程序设计(简称OOP),是当今主流程序设计范型.面向对象的程序是由对象组成的,每个对象(来自于标准库或自定义的)包含对用户公开的特 ...