题意: 给定一个长度为
n
n
n的序列
a
a
a,最大值为
k
k
k,
a
=
{
1
,
2
,
3
,
.
.
.
,
k
,
k
−
1
,
.
.
.
,
k
−
(
n
−
k
)
}
a=\{1,2,3,...,k,k-1,...\ ,k-(n-k)\}
a={1,2,3,...,k,k−1,... ,k−(n−k)}
现在需要你构造一个长度为
k
k
k的排列
p
p
p,序列
b
[
i
]
=
p
[
a
[
i
]
]
b[i]=p[a[i]]
b[i]=p[a[i]] ,保证
b
b
b的逆序对数不多于
a
a
a的逆序对数,且
p
p
p的字典序尽可能大。
数据范围:
1
≤
k
≤
1
0
5
,
k
≤
n
≤
2
k
1\leq k\leq 10^5,k\leq n\leq 2k
1≤k≤105,k≤n≤2k
题解:
b
b
b序列分为以下两部分:
1.
p
[
1
]
,
p
[
2
]
,
.
.
.
,
p
[
k
−
(
n
−
k
)
−
1
]
1. \ p[1],p[2],...\ ,p[k-(n-k)-1]
1. p[1],p[2],... ,p[k−(n−k)−1]
2.
p
[
k
−
(
n
−
k
)
]
,
.
.
.
,
p
[
k
−
1
]
,
p
[
k
]
,
.
.
.
,
p
[
k
−
(
n
−
k
)
+
1
]
,
p
[
k
−
(
n
−
k
)
]
2. \ p[k-(n-k)],...\ ,p[k-1],p[k],...\ ,p[k-(n-k)+1],p[k-(n-k)]
2. p[k−(n−k)],... ,p[k−1],p[k],... ,p[k−(n−k)+1],p[k−(n−k)]
第
2
2
2部分中,不重复的数为:
p
[
k
−
(
n
−
k
)
]
,
p
[
k
−
(
n
−
k
)
+
1
]
,
.
.
.
,
p
[
k
−
1
]
,
p
[
k
]
p[k-(n-k)],p[k-(n-k)+1],...\ ,p[k-1],p[k]
p[k−(n−k)],p[k−(n−k)+1],... ,p[k−1],p[k]
这些数中选取任意两个都可以在第
2
2
2部分中得到一个逆序对,所以在第
2
2
2部分中逆序对数是确定的,故序列
a
a
a第
2
2
2部分和序列
b
b
b第
2
2
2部分的逆序对数一样,只需要去考虑第
1
1
1部分的问题了。
第 1 1 1部分内部 a a a序列的逆序对数为 0 0 0,且其相对于后面部分的逆序对数也是最少的,因为所有小的数都在前面,故第 1 1 1部分内部 b b b序列必须是升序的,且必须是 都为 [ 1 , k ] [1,k] [1,k]中最小的,所以第 1 1 1部分内部 b b b序列为 [ 1 , k − ( n − k ) − 1 ] [1,k-(n-k)-1] [1,k−(n−k)−1]。
- 按照 b b b的第 1 1 1部分构造 p p p的第 1 1 1部分: [ 1 , k − ( n − k ) − 1 ] [1,k-(n-k)-1] [1,k−(n−k)−1]
- 按照
b
b
b的第
2
2
2部分构造
p
p
p的第
2
2
2部分:由于内部的逆序对数确定,要求
p
p
p字典序最大,
故将 [ k − ( n − k ) , k ] [k-(n-k),k] [k−(n−k),k]逆序放置即可。
代码:
#include<bits/stdc++.h>
int n, k, T;
int main()
{
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &k);
for(int i = 1, a = 1, b = k; i <= k; ++i) {
if(i < 2 * k - n) printf("%d", a++);
else printf("%d", b--);
printf("%c", " \n"[i == k]);
}
}
return 0;
}