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