Ordered Permutations
非常典型的 codeforces 小注意力题。
首先,我们发现当排列为 到 的正序数列时, 可以取到最大值。此时,。这是因为区间 的最小值为 ,共 个,区间 的最小值为 ,共 个,以此类推。
我们考虑如下构造过程。假设现在已经构造好了 到 的排列方式,考虑 可以插入到哪些位置。将 插入到已排好的内容中间,将会导致原先的许多区间贡献变得更小,不如将 放在头尾的位置更优。因此,最优排列的构造方案一定是从大往小,每次将当前的数放在头或尾的位置。
一共需决策 个数,每个数都有可能放在首尾两个位置,因此一共有 中方案。超出可以直接输出 -1
。否则,对 进行二进制拆分,根据当前位的值决定该数应该放在头还是尾。可以直接 deque 维护。
#include <cstddef>
#include <deque>
#include <iostream>
using namespace std;
istream& fin = cin;
ostream& fout = cout;
using ui = unsigned int;
using uli = unsigned long long int;
using li = long long int;
int main(void) {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
size_t T;
fin >> T;
while (T--) {
size_t n;
uli k;
fin >> n >> k;
--k;
if (n - 1 < 64 && k >= (1ull << (n - 1))) {
fout << "-1\n";
continue;
}
deque<ui> ans{(ui)n};
for (ui i = n - 1; i > 0; --i) {
if (k & 1)
ans.emplace_back(i);
else
ans.emplace_front(i);
k >>= 1;
}
for (ui i : ans) fout << i << ' ';
fout << '\n';
}
return 0;
}