LG·快速排序【模拟】

2020年11月3日提高组【校测】 luogu U138420 快速排序

Description–

> l i n k link link

小W最近学习了快速排序,写出了下述的代码
在这里插入图片描述
这里开始 l o w = 0 , h i g h = N low=0,high=N low=0high=N,数组 a a a 1 − N 1-N 1N 的一个排列

采用随机优化的快速排序是很难碰到最坏情况的,但是小W偷偷修改了运行环境,控制了随机数的生成,使得随机数依次为 a 1 , a 2 , a 3 , . . . , a k , a 1 , . . . a1,a2,a3,...,ak,a1,... a1,a2,a3,...,ak,a1,...不断循环。

一个排列在这样的随机数下效果最差即递归的深度最深,请求出这个排列


Input–

第一行两个整数 N N N k k k
接下来 k k k 行,每行一个数字,表示 a 1 a1 a1 a k ak ak

Output–

N N N 行整数,为 1 − N 1-N 1N 的一个排列
(若有多个排列满足条件,输出其中字典序最小的那个排列


Sample Input–

样例1

3 1
0

样例2

4 2
1
0

样例3

1 1
0

Sample Output–

样例1

1
2
3

样例2

1
4
2
3

样例3

1

说明–

样例解释

  • 对于样例 1 1 1
    ( 1 , 2 , 3 ) (1,2,3) (1,2,3) 递归深度为 3 3 3 层,字典序最小
  • 对于样例 2 2 2
    ( 1 , 4 , 2 , 3 ) (1, 4, 2, 3) (1,4,2,3) 递归深度为 4 4 4 层,字典序最小
    ( 1 , 2 , 3 , 4 ) − > ( 1 ) 2 ( 3 , 4 ) − > 123 ( 4 ) (1,2,3,4) -> (1) 2 (3,4) -> 1 2 3 (4) (1,2,3,4)>(1)2(3,4)>123(4) 字典序小,但是只有 3 3 3 层深度

数据范围
对于 40 % 40\% 40% 的数据, 1 = N , k < = 10 1=N,k<=10 1=N,k<=10
对于 70 % 70\% 70% 的数据, 1 < = N , k < = 10000 1<=N,k<=10000 1<=N,k<=10000
对于 100 % 100\% 100% 的数据, 1 < = N , k < = 50000 , 0 < = a i < = 1 0 9 1<=N,k<=50000, 0<=ai<=10^9 1<=N,k<=50000,0<=ai<=109


解题思路–

每次中枢选择时选中最值可以使得只排除掉一个数字,从而得到最大递归深度n。
要使得字典序最小,则若该位置左边的全部数字已经填满,则该位置放置当前处理的最小
值,否则放置最大值。(因为更小的应该放左边


代码–

#include <iostream>
#include <cstdio>

using namespace std;

int n, k, l, r, x, kw, a[50005], b[50005], w[50005];

int main()
{
	scanf("%d%d", &n, &k);
	l = kw = 1, r = n;
	for (int i = 0; i < k; ++i)
	  scanf("%d", &a[i]);
	for (int i = 1; i <= n; ++i) b[i] = i;
	for (int i = 0; i < n; ++i)              //l为每次处理时的最小值,r为最大值
	{
		x = a[i % k] % (n - i) + l;  
		if (b[x] == kw) //显而易见,kw = 空位 (QAQ
		{
			w[b[x]] = l; 
			swap(b[x], b[l]);
			l++;
			while (w[kw]) kw++;
		}
		else
		{
			w[b[x]] = r;
			swap(b[x], b[l]);
			swap(b[l], b[r]);
			r--; 
		}
	}
	for (int i = 1; i <= n; ++i)
	  printf("%d\n", w[i]);
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值