给定一个长度为n(n<=100000)的排列p (1~n中每个数各出现一次),求字典序比这个排列大的所有长度为n的排列中,字典序最小的排列。如果这个排列不存在,则输出-1。
我们称两个排列A,B满足A的字典序小于B当且仅当存在一个整数i,满足1<=i<=n,A[i]<B[i],且对于所有满足1<=j<i的整数j均有A[j]=B[j]。
提示:首先找到一个pos,使得p[pos....n]递减且p[pos-1]<p[pos],如果找不到那么直接输出-1; 接下来在有序序列p[pos....n]中通过二分查找得到比p[pos-1]大的最小整数p[l],并交换p[pos-1]与p[l];最后将p[pos....n]前后翻转。不难发现通过上述方法得到的排列一定是答案。
#include<cstdio> using namespace std; int n,i,l,r,mid,t,rv,pos,p[100010]; int main () { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&p[i]); pos=n; while(______(1)______) pos--; if(pos==1){ puts("-1"); return 0; } l=pos; r=n; while(l<r){ _____(2)________ if(_____(3)______) l=mid; else r=mid-1; } t=p[pos-1]; p[pos-1]=p[l]; p[l]=t; for(i=pos;i<=_____(4)_______;i++){ rv=_____(5)______; t=p[i]; p[i]=p[rv]; p[rv]=t; } for(i=1;i<=n;i++){ printf("%d",p[i]); if(i==n) putchar('\n'); else putchar(' '); } return 0; }