题意:给定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; }