CF1508B Almost Sorted
题目传送门。
题意简述:定义一个排列
a_1,a_2,\cdots,a_n 是 “几乎有序” 的,当且仅当对于每一个位置i\ (1\leq i<n) ,满足a_{i+1}\geq a_i-1 。请求出长度为n 的所有 “几乎有序” 的排列中,字典序第k 小的那一个。 多组询问,1\leq \sum n\leq 10^5 ,1\leq k\leq 10^{18} 。
考虑一个 “几乎有序” 的排列满足什么性质:给定的
上面的形式又可以这样描述:将
不难发现,每一种切割方案,就对应了一个 “几乎有序” 的排列。反过来,如果有一个 “几乎有序” 的排列,那么我们就可以构造出相应的切割方案。也就是说,切割方案与符合条件的排列是一一对应的。
切割方案有
至于字典序,可以证明:如果将所有空隙是(
简要证明:设长度为
代码比较好写,注意特判一下
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll n,k;
void solve(){
cin>>n>>k,k--;
if(n<62&&k>>n-1)return puts("-1"),void();
for(int i=1,p=1;i<=n;i=p+1,p=i){
while(p<n&&n-p<=62&&(k>>n-p-1)&1)p++;
for(int j=p;j>=i;j--)cout<<j<<" ";
} cout<<endl;
}
int main(){
int t=1;
cin>>t;
while(t--)solve();
return 0;
}