1、UVA 11525 Permutation
题意:求1~k这k个数中第N个排列。(N从0开始记)。N=sum(Si*(k-i)!)(1≤i≤k)
思路:根据N的值的性质,联系康拓展开,不妨发现第i位的值为剩下没用的数中从小到大第Si+1个。可以用线段树来记录区间内没有用的数的个数。
1 #include<iostream> 2 using namespace std; 3 int k; 4 const int maxk = 50010; 5 int numk[maxk]; 6 int tree[maxk << 2]; 7 void Build(int root, int l, int r) 8 { 9 if (l == r) 10 { 11 tree[root] = 1; 12 return; 13 } 14 int mid = (l + r) / 2; 15 Build(root * 2, l, mid); 16 Build(root * 2 + 1, mid + 1, r); 17 tree[root] = tree[root * 2] + tree[root * 2 + 1]; 18 } 19 int pos; 20 void Query(int root, int l, int r, int x) 21 { 22 if (l == r) 23 { 24 tree[root] = 0; 25 pos = l; 26 return; 27 } 28 int mid = (l + r) / 2; 29 if (x <= tree[root*2]) Query(root * 2, l, mid, x); 30 else Query(root * 2 + 1, mid + 1, r, x - tree[root * 2]); 31 tree[root] = tree[root * 2] + tree[root * 2 + 1]; 32 } 33 int main() 34 { 35 int t; 36 scanf("%d", &t); 37 while (t--) 38 { 39 scanf("%d", &k); 40 Build(1, 1, k); 41 for (int i = 1; i <= k; i++) 42 { 43 int num; 44 scanf("%d", &num); 45 if (i > 1) printf(" "); 46 pos = 0; 47 Query(1, 1, k, num + 1); 48 printf("%d", pos); 49 } 50 printf("\n"); 51 } 52 return 0; 53 }
时间: 2024-10-24 00:45:03