最慢的快排

小nod 新学了快速排序,并且学会了用random函数获取随机中枢避免最坏复杂度的出现。
代码如下:

void Qsort(int a[], int low, int high)
{
    if(low >= high) return;   
    int first = low;
    int last = high;
    int key_index = (rand() % (high - low + 1)) + low;
    swap(a[first], a[key_index]);
    int key = a[first];    /*用数组的第一个记录作为枢轴*/
    while(first < last) {
        while(first < last && a[last] >= key) --last;
        a[first] = a[last];            /*将比第一个小的移到低端*/
        while(first < last && a[first] <= key) ++first;
        a[last] = a[first];            /*将比第一个大的移到高端*/
    }
    a[first] = key;         /*枢轴记录到位*/
    Qsort(a, low, first - 1);
    Qsort(a, first + 1, high);
}

号称这份代码跑的比谁都快,并且到处找人炫耀。


夹克老爷 为了教育他,事先更改了测试机的环境,构造了大小为k的数组r,使得快排开始后,第i次调用rand函数时返回的是r[i%k](注意,这里的i从第0次开始),给出r数组中的k个数
你能构造一个1-N的排列让测试机上运行的快排代码递归深度最大吗?(Qsort函数的递归调用深度最大,不考虑尾递归优化)

PS:

上面这句话里的“第i次调用”是从第0次调用开始的...

也就是简单的按照从前往后循环使用r数组...

输出递归深度最大的排列中字典序最小的那个排列。
例如:
3 1
0
每次选择第0个数字作为枢轴,最大递归3层,(1,2,3)、(3,2,1)、(3,1,2)等排列都符合要求,其中字典序最小的是(1,2,3)
答案为(1,2,3)

3 1
1
每次选择第1个数字作为枢轴,最大递归3层,(2,1,3)、(3,1,2)、(1,3,2)等排列都符合要求,其中字典序最小的是(1,3,2)
答案为(1,3,2)

4 2
1 2
循环使用1、2数字作为枢轴,最大递归4层,(3,4,1,2)、(3,1,4,2)、(1,4,3,2)等排列都符合要求,其中字典序最小的是(1,4,3,2)
答案为(1,4,3,2)

输入格式

第一行两个整数N, K.(1 <= N <= 50000, 1 <= K <= 50000)。 第2 - K + 1行:每行1个数对应数组r中的元素。(0 <= r[i] <= 10^9)

输出格式

N行整数,1-N的一个排列,使得上述快排代码递归深度最大,输出其中字典序最小的那个排列。

输入样例

3 1
0

输出样例

1
2
3
#include <bits/stdc++.h>
using namespace std;
int r[50005],res[50005],ori_idx[50005],n,k;
int main(){
	cin>>n>>k;
	for(int i=0;i<k;i++){
		cin>>r[i];
	}
	int min_num=1,max_num=n,min_idx=0;
	for(int i=0;i<n;i++){
		ori_idx[i]=i;
		res[i]=-1;
	}
	for(int i=0;i<n;i++){
		int rand_idx=min_num-1+r[i%k]%(max_num-min_num+1);
		if(ori_idx[rand_idx]==min_idx){
			res[min_idx]=min_num;
			swap(ori_idx[rand_idx],ori_idx[min_num-1]);
			++min_num;
			for(;min_idx<n&&res[min_idx]>=0;)
				++min_idx;
		}else{
			res[ori_idx[rand_idx]]=max_num;
			swap(ori_idx[rand_idx],ori_idx[min_num-1]);
			swap(ori_idx[max_num-1],ori_idx[min_num-1]);
			--max_num;
		}
	}
	for(int i=0;i<n;i++){
		cout<<res[i]<<endl;
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值