Test instructions: There is a sequence of 1 to K, the minimum is 1 2 ... k, the largest is K k-1 ... 1, gives the calculation method of N, n = s0 * (k-1)! + S1 * (k-2)! + ... + sk-1 * 0!, gives the s1...sk, the sequence of the nth large in the output sequence.
The puzzle: Finding the results by finding a rule can be recursive, such as a third set of examples:
4
2 1 1 0
Then n = 2 * 3! + 1 * 2! + 1 * 1! + 0 * 0! = 15, by the arrangement of the 1~4 all down, found 3! is the interval to replace the first number, 2! is the interval for replacing the second number, and so on, then 2*3! is obviously a sequence that begins with the number 3, which is S0 + 1, because it has been 1 sequences beginning with 2 and beginning with two. Then the number 2 is S1 + 1 as a sequence of the 2nd number, according to this law can be found:
1 2 3 4 found the first S0 + 1 digits, 3 are used
1 2 4 Find the S1 + 1 digits, 2 are used
1 4 found the S2 + 1 numbers, 4 are used
1 Find the S3 + 1 numbers, 1 are used
So the final sequence is 3 2 4 1.
Then just think of if the s[i] + 1 numbers if not used to mark has been used, if it has been marked to look back to the first unused number tag, but N has 50000, so think of using a line segment tree to reduce time (thought), each node of the segment tree is the case of whether all child nodes are marked.
#include <cstdio> #include <cstring> #include <algorithm> #include <vector>using namespace std;Const intN =50005;intN, S[n], sum[n <<2];void Pushup (intk) {Sum[k] = Sum[k *2] + sum[k *2+1];} void Build (intKint Left,int Right) {if( Left== Right) {Sum[k] =1; Return }int Mid= ( Left+ Right) /2; Build (k *2, Left,Mid); Build (k *2+1,Mid+1, Right); Pushup (k);}intQueryintKint Left,int Right,intx) {if( Left== Right) {Sum[k] =0; Return Left; }int Mid= ( Left+ Right) /2, Res;if(Sum[k *2] >= x) res = query (k *2, Left,Mid, x);Elseres = query (k *2+1,Mid+1, Right, X-sum[k *2]); Pushup (k); return res;}intMain () {intT scanf"%d", &t); while(t--) {scanf ("%d", &n); Build1,1, n); for(inti =0; I < n; i++) scanf ("%d", &s[i]); printf"%d", Query (1,1, N, s[0] +1)); for(inti =1; I < n; i++) printf ("%d", Query (1,1, N, S[i] +1)); printf"\ n"); } return0;}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
UVA 11525 (single point modification)