题意:给定N与K(均为正整数)可以确定第K个全排列(1..N的全排列),但N较大,现以N=sigma(Si×(K-i)!)(i=1..K)的形式,输入K以及Si,i=1..K,请输出第K个全排列
分析:逆向去想,对于一个给定的全排列可以确定它的序号K,K的表达式形式与N类似,发现从Si可以确定第K个全排列中的第i项,具体用线段树实现查找第i项即可。
代码:
#include <stdio.h>
#include <iostream>
using namespace std;
struct segment{
int l, r, k;
}p[200000];
void build(int i, int l, int r){
p[i].l = l;
p[i].r = r;
p[i].k = r - l + 1;
if(l==r)
return;
build(2*i, l, (l+r)/2);
build(2*i+1, (l+r)/2+1, r);
}
int query(int k, int i){
p[i].k--;
if(p[i].l == p[i].r)
return p[i].l;
if(k > p[2*i].k)
return query(k - p[2*i].k, 2*i+1);
else
return query(k, 2*i);
}
int a[50005];
int main(){
// freopen("in.txt", "r", stdin);
int cas;
scanf("%d", &cas);
while(cas--){
int k;
scanf("%d", &k);
build(1, 1, k);
int i;
for(i=0; i
scanf("%d", a+i);
a[i]++;
}
for(i=0; i
int ans = query(a[i], 1);
if(i) printf(" ");
printf("%d", ans);
}
printf("\n");
}
return 0;
}