问题 4176 --next_permutation问题

4176: next_permutation问题★★★

时间限制: 1 Sec  内存限制: 128 MB
提交: 227  解决: 160
[提交][状态][命题人:]

题目描述

给定一个长度为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;
}


输入

输出

样例输入
Copy
5
1 3 5 4 2
样例输出
Copy
1 4 2 3 5

提示

来源

[提交][状态]