2020年11月3日提高组【校测】 luogu U138420 快速排序
Description–
小W最近学习了快速排序,写出了下述的代码
这里开始
l
o
w
=
0
,
h
i
g
h
=
N
low=0,high=N
low=0,high=N,数组
a
a
a 为
1
−
N
1-N
1−N 的一个排列
采用随机优化的快速排序是很难碰到最坏情况的,但是小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
1−N 的一个排列
(若有多个排列满足条件,输出其中字典序最小的那个排列
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;
}