zoukankan      html  css  js  c++  java
  • 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
    ",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;
    }
    
    
  • 相关阅读:
    python学习,day4:装饰器的使用示例
    python学习,day3:函数式编程,递归和高阶函数
    JZ高中OJ 1385. 直角三角形
    JZ高中OJ 1382. 区间
    JZ高中OJ 3404. [NOIP2013模拟]卡牌游戏
    JZ高中OJ 3403. [NOIP2013模拟] 数列变换
    JZ高中OJ 1433. 数码问题
    JZ初中OJ 1339. disease
    JZ高中OJ 1432. 输油管道
    JZ初中OJ 1342. [南海2009初中]cowtract
  • 原文地址:https://www.cnblogs.com/wzl19981116/p/10752766.html
Copyright © 2011-2022 走看看