D e s c r i p t i o n Description Description
给出
k
k
k个数
a
1
,
a
2
…
a
k
a_1,a_2…a_k
a1,a2…ak
令
n
=
∑
i
=
1
k
a
i
×
(
K
−
i
)
!
n=\sum_{i=1}^ka_i\times (K-i)!
n=∑i=1kai×(K−i)!
1
−
k
1-k
1−k的按照字典序排序的第n个排列
S o l u t i o n Solution Solution
逆康托展开
题目给出的
k
k
k个数已经做完第一步了
其实就是每次取出
1
−
k
1-k
1−k中第
a
i
a_i
ai大的数
,
,
,取完删掉就好了
权值线段树维护(
A c c e p t e d c o d e Accepted\ code Accepted code
#include<queue>
#include<cstdio>
#define ls (now << 1)
#define rs (now << 1 | 1)
using namespace std;
struct Node {
int l, r, num;
}t[200005];
int T, n;
void build(int now, int l, int r) {
t[now].l = l; t[now].r = r;
if (l == r) { t[now].num = 1; return; }
int mid = l + r >> 1;
build(ls, l, mid), build(rs, mid + 1, r);
t[now].num = t[ls].num + t[rs].num;
}
int modify(int now, int x) {
if (t[now].l == t[now].r) {
t[now].num = 0; return t[now].l;
}
int s;
if (t[ls].num >= x) s = modify(ls, x);
else s = modify(rs, x - t[ls].num);
t[now].num = t[ls].num + t[rs].num;
return s;
}
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
build(1, 1, n);
for (int x, i = 1; i <= n; ++i) {
scanf("%d", &x);
printf("%d", modify(1, x + 1));
putchar(i == n ? '\n' : ' ');
}
}
}