首页 > 代码库 > Permutation
Permutation
uva11525:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2520
题意:求1,2,3,4,.....k个数所形成的全排列中的第n个。其中n的是由 计算出,给出每个si。
题解:这一题如果知道康托展开的话,就很简单。X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!表示求第X个全排列的话,那么第一个数就是所有数中第 an+1小的数,第二个数就是剩余数中第an-1+1小的数。知道了这个结论之后,就可以用线段树来维护。每次查找第k个数,然后把这个数删除。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=50004; 7 struct Segtree{ 8 int l,r,sum; 9 inline int mid(){10 return (l+r)/2;11 }12 }num[N*4];13 void pushup(int rt){14 num[rt].sum=num[rt<<1].sum+num[rt<<1|1].sum;15 }16 void build(int rt ,int l,int r){17 num[rt].l=l;18 num[rt].r=r;19 if(l==r){20 num[rt].sum=1;21 return;22 }23 int mid=num[rt].mid();24 build(rt<<1,l,mid);25 build(rt<<1|1,mid+1,r);26 pushup(rt);27 }28 int query(int pos,int rt){29 if(num[rt].l==num[rt].r){30 num[rt].sum=0;31 return num[rt].l;32 }33 int ans;34 if(num[rt<<1].sum>=pos)ans=query(pos,rt<<1);35 else ans=query(pos-num[rt<<1].sum,rt<<1|1);36 pushup(rt);37 return ans;38 }39 int main(){40 int k, t,cas;41 scanf("%d",&cas);42 while(cas--){43 scanf("%d",&k);44 build(1,1,k);45 for(int i=1;i<=k;i++){46 scanf("%d",&t);47 int ans=query(t+1,1);48 if(i<k)printf("%d ",ans);49 else printf("%d\n",ans);50 }51 }52 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。