UVA 11525 Permutation ——(线段树,脑筋急转弯)

  只要注意到对于譬如:S1*(k-1)! 因为后面k-1个数字的全排列个数刚好是(k-1)!,那么第一个数字就是没有取过的数字的第(S1+1)个即可。取走这个数字以后这个数字就不能再用了,依次类推即可得到整个排列了。

  那么随便用线段树维护一下即可。

  代码如下:

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <string.h>
 4 #define t_mid (l+r>>1)
 5 #define ls (o<<1)
 6 #define rs (o<<1|1)
 7 #define lson ls,l,t_mid
 8 #define rson rs,t_mid+1,r
 9 using namespace std;
10 const int N = 5e4 + 5;
11 
12 int c[N<<2];
13 void up(int o) {c[o] = c[ls] + c[rs];}
14 int query(int o,int l,int r,int sum)
15 {
16     if(l == r && sum == 1)
17     {
18         return l;
19     }
20     if(sum <= c[ls]) return query(lson,sum);
21     else return query(rson,sum - c[ls]);
22 }
23 void update(int o,int l,int r,int pos,int f)
24 {
25     if(l == r)
26     {
27         c[o] = f;
28         return ;
29     }
30     if(pos <= t_mid) update(lson,pos,f);
31     else update(rson,pos,f);
32     up(o);
33 }
34 void build(int o,int l,int r)
35 {
36     if(l == r)
37     {
38         c[o] = 1;
39         return ;
40     }
41     build(lson);
42     build(rson);
43     up(o);
44 }
45 
46 int T,n;
47 
48 int main()
49 {
50     scanf("%d",&T);
51     while(T--)
52     {
53         scanf("%d",&n);
54         build(1,1,n);
55         for(int i=1;i<=n;i++)
56         {
57             int x;
58             scanf("%d",&x);
59             int t = query(1,1,n,x+1);
60             printf("%d%c",t,i==n?'
':' ');
61             update(1,1,n,t,0);
62         }
63     }
64     return 0;
65 }
原文地址:https://www.cnblogs.com/zzyDS/p/6664574.html