1 条题解

  • 1
    @ 2025-3-14 17:48:52

    题型:一道构造题(通过构造条件,推原始序列)

    给出一个 nk ,求满足归并排序函数调用次数为 k 的,且长度为 n 的序列。

    归并排序的模板:

    void merge_sort(int l,int r){
    	if(l==r) return;
    	int m=(l+r)/2;
    	merge_sort(l,m);
    	merge_sort(m+1,r);
        ……(以下略)
    }
    

    可以看出,每次都会调用 2 次归并排序函数,再加上开头的一次(检查序列是否已经有序),得出:k 一定是奇数。( 2 是偶数,加上 1 一定是奇数)

    所以先特判:偶数一定是 -1

    考虑将调用次数加 2 ,因为区间 [l,r) [l,r) 递增,则必然要让 [l,mid) [l,mid) [mid,r) [mid,r) 不递增,但 [l,r) [l,r) 仍然递增。只需 swap(a[mid1],a[mid])swap(a[mid-1],a[mid]) 即可。

    结束条件: kk 达到标准或单独元素(没有必要交换)。

    特判2:当所有调用都为单一元素时,k>0k>0 则输出 -1 (没有元素可交换了,但还没有达标)。

    例如:n=5,k=11 n = 5,k = 11 时,最大交换次数为 251=92*5-1=9 次,不满足条件,输出 -1

    #include<bits/stdc++.h>
    using namespace std;
    int n,k,a[100001];
    void merge_sort(int l,int r){
    	if(l+1==r||k<=0) return;//单一元素或k达标时return掉。
    	int m=(l+r)/2;
    	swap(a[m-1],a[m]);//交换,使[l,r)不递增。
    	k-=2;//调用2次
    	merge_sort(l,m);
    	merge_sort(m,r);
    }
    int main(){
    	cin>>n>>k;
    	if(k%2==0){//特判1:k非偶数。
    		cout<<"-1"<<endl;
    		return 0;
    	}
    	k--;
    	for(int i=0;i<n;i++) a[i]=i+1;//重置数组为1~k
    	merge_sort(0,n);
    	if(k>0){//特判2:分完时k仍然>0,则输出-1
    		cout<<"-1"<<endl;
    		return 0;
    	}
    	for(int i=0;i<n;i++){//否则输出符合条件的序列
    		cout<<a[i]<<" ";
    	}
    		
    	return 0;
    }
    

    信息

    ID
    28826
    时间
    2000ms
    内存
    256MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者