Problem F
Permutation
Input: Standard Input
Output: Standard Output
Given N and K find the N’th permutation of the integers from 1 to K when those permutations are lexicographically ordered. N starts from 0. Since N is very large N will be represented by a sequence of K non-negative integers S1, S2 ,…, Sk. From this sequence of integers N can be calculated with the following expression.
Input
First line of the input contains T(≤10) the number of test cases. Each of these test cases consists of 2 lines. First line contains a integer K(1≤K≤50000). Next line contains K integers S1, S2 ,…, Sk.(0≤Si≤K-i).
Output
For each test case output contains N’th permutation of the integers from 1 to K. These K integers should be separated by a single space.
Sample Input Output for Sample Input
4 3 2 1 0 3 1 0 0 4 2 1 1 0 4 1 2 1 0
|
3 2 1 2 1 3 3 2 4 1 2 4 3 1
|
Problemsetter: Abdullah al Mahmud
Special Thanks: Manzurur Rahman Khan
题意:
给出 T(1 ~ 10),代表有 T 个 case,每个 case 给出一个 N (1 ~ 50000),给出 N 个数,后给出式子 M = ,输出第 M 个 1 ~ K 的序列是什么。
思路:
线段树 + 单点更新。观察式子,反过来看,比如求K = 4 中的排列 3 2 4 1 是属于第几个排列,那么就是等于
2 X 3!+ 1 X 2! + 1 X 1! + 0 X 1!,得出来的式子刚好与给出的式子 M 吻合,说明 Si 是寻找序列的第 Si 个数。得出来之后用线段树维护即可。
AC:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAX = 50005; int sum[MAX * 3]; int num[MAX]; void push_up (int node) { sum[node] = sum[node << 1] + sum[node << 1 | 1]; } void build (int node, int l, int r) { if (l == r) { sum[node] = 1; } else { int mid = (r + l) >> 1; build(node << 1, l, mid); build(node << 1 | 1, mid + 1, r); push_up(node); } } void updata (int node, int l, int r, int i) { if (l == r) { if (l == i) sum[node] = 0; return; } int mid = (r + l) >> 1; if (i <= mid) updata(node << 1, l, mid, i); else updata(node << 1 | 1, mid + 1, r, i); push_up(node); } int query (int node, int l, int r, int k) { if (l == r) return l; int mid = (r + l) >> 1; if (k < sum[node << 1]) return query(node << 1, l, mid, k); return query(node << 1 | 1, mid + 1, r, k - sum[node << 1]); } int main() { int t; scanf("%d", &t); while (t--) { int n; scanf("%d", &n); build(1, 1, n); for (int i = 0; i < n; ++i) { scanf("%d", &num[i]); } for (int i = 0; i < n; ++i) { int in = query(1, 1, n, num[i]); printf("%d", in); updata(1, 1, n, in); i == n - 1 ? printf("\n") : printf(" "); } } return 0; }