873D. Merge Sort

Merge sort is a well-known sorting algorithm. The main function that sorts the elements of array a with indices from [l,?r) can be implemented as follows:

If the segment [l,?r) is already sorted in non-descending order (that is, for any i such that l?≤?i?<?r?-?1 a[i]?≤?a[i?+?1]), then end the function call;
Let ;
Call mergesort(a,?l,?mid);
Call mergesort(a,?mid,?r);
Merge segments [l,?mid) and [mid,?r), making the segment [l,?r) sorted in non-descending order. The merge algorithm doesn‘t call any other functions.
The array in this problem is 0-indexed, so to sort the whole array, you need to call mergesort(a,?0,?n).

The number of calls of function mergesort is very important, so Ivan has decided to calculate it while sorting the array. For example, if a?=?{1,?2,?3,?4}, then there will be 1 call of mergesort — mergesort(0,?4), which will check that the array is sorted and then end. If a?=?{2,?1,?3}, then the number of calls is 3: first of all, you call mergesort(0,?3), which then sets mid?=?1 and calls mergesort(0,?1) and mergesort(1,?3), which do not perform any recursive calls because segments (0,?1) and (1,?3) are sorted.

Ivan has implemented the program that counts the number of mergesort calls, but now he needs to test it. To do this, he needs to find an array a such that a is a permutation of size n (that is, the number of elements in a is n, and every integer number from [1,?n] can be found in this array), and the number of mergesort calls when sorting the array is exactly k.

Help Ivan to find an array he wants!

Input
The first line contains two numbers n and k (1?≤?n?≤?100000, 1?≤?k?≤?200000) — the size of a desired permutation and the number of mergesort calls required to sort it.

Output
If a permutation of size n such that there will be exactly k calls of mergesort while sorting it doesn‘t exist, output ?-?1. Otherwise output n integer numbers a[0],?a[1],?...,?a[n?-?1] — the elements of a permutation that would meet the required conditions. If there are multiple answers, print any of them.

Examples
inputCopy
3 3
outputCopy
2 1 3
inputCopy
4 1
outputCopy
1 2 3 4
inputCopy
5 6
outputCopy
-1

题目要你构造长度为N,调用归并排序次数为K 的序列,如果已经排好序,他将不在调用归并排序

做法,首先,这个调用除了第一次,之后肯定都是调用两次,所以如果是偶数的话肯定是不可以的,所以首先排除次数是偶数的

之后,调用的时候,分成两边,然后K在传递的时候,如果K/2是奇数,则K1=K2=K/2,否则K1=K2-2;
因为我们的下两次调用也要保证两边为奇数次,
最后,如果当前调用区间只有一个数字,就可以返回了,如果区间有两个数字,并且调用时K为2,则交换这两个数字
如果K为2,则可以直接交换mid-1和mid,每次定义一个tot+1或者+2最后看是否等于K,是则输出,不是则-1

#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<stdio.h>
#include<float.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define sf scanf
#define pf printf
#define fi first
#define se second
#define mp make_pair
#define pii pair<int,int>
#define scf(x) scanf("%d",&x)
#define prf(x) printf("%d\n",x)
#define scff(x,y) scanf("%d%d",&x,&y)
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=a;i>=n;i--)
#define mm(x,b) memset((x),(b),sizeof(x))
#define scfff(x,y,z) scanf("%d%d%d",&x,&y,&z)
typedef long long ll;
const ll mod=1e9+7;
using namespace std;

const double eps=1e-8;
const int inf=0x3f3f3f3f;
const double pi=acos(-1.0);
const int N=2e5+10;
int a[N];
int tot=0;
void dfs(int l,int r,int q)
{
    tot++;
    int mid=(l+r)>>1;
    if(!q) return ;
    if(q==2&&mid>0)
    {
        q=0;tot+=2;
        swap(a[mid-1],a[mid]);
        return ;
    }
    if(l+2==r){
        tot+=2;
        swap(a[l],a[l+1]); return;
    }
    if(mid==l) return;
    int k1,k2;

    k1=k2=q/2;
    if((q/2)%2==0)
    k1--,k2++;
    if(q) dfs(l,mid,k1-1);
    if(q) dfs(mid,r,k2-1);
}
int main()
{
    int n,k;cin>>n>>k;
    rep(i,0,n)  a[i]=i+1;
    if(!(k&1)) { cout<<"-1"; return 0;  }

    dfs(0,n,k-1);
    if(tot==k)
    {
        cout<<a[0];
        rep(i,1,n) cout<<" "<<a[i];
    }else
    cout<<"-1";
    return 0;
}

原文地址:https://www.cnblogs.com/wzl19981116/p/10752766.html

时间: 2024-10-12 20:14:26

873D. Merge Sort的相关文章

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

归并排序(Merge Sort)与快速排序思想类似:将待排序数据分成两部分,继续将两个子部分进行递归的归并排序:然后将已经有序的两个子部分进行合并,最终完成排序.其时间复杂度与快速排序均为O(nlogn),但是归并排序除了递归调用间接使用了辅助空间栈,还需要额外的O(n)空间进行临时存储.从此角度归并排序略逊于快速排序,但是归并排序是一种稳定的排序算法,快速排序则不然. 所谓稳定排序,表示对于具有相同值的多个元素,其间的先后顺序保持不变.对于基本数据类型而言,一个排序算法是否稳定,影响很小,但是

排序算法二:归并排序(Merge sort)

归并排序(Merge sort)用到了分治思想,即分-治-合三步,算法平均时间复杂度是o(nlgn). (一)算法实现 1 private void merge_sort(int[] array, int first, int last) { 2 if (first + 1 < last) { 3 int mid = (first + last) / 2; 4 merge_sort(array, first, mid); 5 merge_sort(array, mid, last); 6 7 /

SQL Tuning 基础概述06 - 表的连接方式:Nested Loops Join,Merge Sort Join &amp; Hash Join

nested loops join 嵌套循环 merge sort join 排序合并 hash join 哈希连接 nested loops join(嵌套循环)   驱动表返回几条结果集,被驱动表访问多少次,有驱动顺序,无须排序,无任何限制. 驱动表限制条件有索引,被驱动表连接条件有索引. hints:use_nl() merge sort join(排序合并)   驱动表和被驱动表都是最多访问1次,无驱动顺序,需要排序(SORT_AREA_SIZE),连接条件是<>或like导致无法使用

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

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie merge sort ---------------------------------------------------------------------- 描述:归并排序 思路: 1.将区间对半分割 2.对左.右段分别排序 3.利用inplace_merge将左.右段合并成为一个完整的有序序列 复杂度:O(nlog n) 源码: template<class Bidirection

经典排序算法 - 归并排序Merge sort

经典排序算法 - 归并排序Merge sort 原理,把原始数组分成若干子数组,对每个子数组进行排序, 继续把子数组与子数组合并,合并后仍然有序,直到所有合并完,形成有序的数组 举例 无序数组[6 2 4 1 5 9] 先看一下每一个步骤下的状态,完了再看合并细节 第一步 [6 2 4 1 5 9]原始状态 第二步 [2 6] [1 4] [5 9]两两合并排序,排序细节后边介绍 第三步 [1 2 4 6] [5 9]继续两组两组合并 第四步 [1 2 4 5 6 9]合并完成,排序完成 输出结

1.7 逆序数与归并排序[inversion pairs by merge sort]

[本文链接] http://www.cnblogs.com/hellogiser/p/inversion-pairs-by-merge-sort.html [题目] 编程之美1.7光影切割问题可以进一步将问题转化为求逆序数问题. [分析] 求解逆序对问题与MergeSort类似,只需要对MergeSort稍作修改即可实现.MergeSort是采用分治法的思想,若需要排序A[p...r],则可以对半分成A[p...q]和A[q...r],然后将这有序的两部分Merge,而Merge的过程为Θ(n)

oracle表之间的连接之------&gt;排序合并连接(Merge Sort Join)

排序合并连接 (Sort Merge Join)是一种两个表在做连接时用排序操作(Sort)和合并操作(Merge)来得到连接结果集的连接方法. 对于排序合并连接的优缺点及适用场景如下: a,通常情况下,排序合并连接的执行效率远不如哈希连接,但前者的使用范围更广,因为哈希连接只能用于等值连接条件,而排序合并连接还能用于其他连接条件(如<,<=,>.>=) b,通常情况下,排序合并连接并不适合OLTP类型的系统,其本质原因是对于因为OLTP类型系统而言,排序是非常昂贵的操作,当然,如

Iterative (non-recursive) Merge Sort

An iterative way of writing merge sort: #include <iostream> using namespace std; void merge(int A[], int l, int r, int e, int B[]) { int i = l, j = r, k = l; while (i<r && j<e) { if (A[i] > A[j]) B[k++] = A[j++]; else B[k++] = A[i++

Codeforces 847B - Preparing for Merge Sort

847B - Preparing for Merge Sort 思路:前面的排序的最后一个一定大于后面的排序的最后一个.所以判断要不要开始新的排序只要拿当前值和上一个排序最后一个比较就可以了. 代码: #include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=2e5+5; int