【NOIP模拟】排序

题面

众所周知,熟练掌握至少一种排序算法是参加NOIP的必备技能。常见的排序算法有冒泡排序、归并排序、快速排序、奇偶排序、猴子排序、梳排序、鸡尾酒排序、臭皮匠排序等。  在这里,介绍一种利用栈进行排序的方法。例如,当数组中的元素为 1, 3, 2 时,我们可以利用栈对其进行排序: 1 入栈; 3 入栈; 3 出栈; 2 入栈; 2 出栈; 1 出栈。在这个例子中,出栈序列是 3, 2, 1,因而实现了对数组的排序。  遗憾的是,在不打乱入栈顺序的前提下,有时仅仅借助一个栈是不能实现对数组的完全排序。例如给定数组 2, 1, 3,借助一个栈,能获得的字典序最大的出栈序列是 3, 1, 2。(2 入栈; 1 入栈; 3 入栈; 3 出栈; 1 出栈; 2 出栈)  现请你借助一个栈,在不打乱入栈顺序的情况下,对数组进行从大到小排序。当无法完全排序时,请输出字典序最大的出栈序列。

分析

其实也是一眼题,但是不幸死于细节(蠢到成功被样例误导)

要让字典序最大,就要让相对大的尽量早出来,所以需要处理一个后缀最大

即在这个数后面的数中,最大的数是多少

我们需要维护一个栈和未被输出的最大值outmax,如果当前栈顶就是outmax,那么就先输出它,然后用当前栈顶的后缀最大更新outmax

然后判断当前栈顶是否比outmax要大,如果是,一直输出并弹栈。当时就是这考虑漏了...因为样例是2 1 5 3 4

最后所有数都入过栈后,输出栈内剩下的数

代码

#include<bits/stdc++.h>
using namespace std;
#define N 1010000
int n,top,cnt,outmax;
int a[N],s[N],ans[N],maxs[N];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    outmax=n;
    for(int i=n;i>=1;i--)
        maxs[i]=max(maxs[i+1],a[i]);
    for(int i=1;i<=n;i++)
    {
        s[++top]=a[i];
        if(a[i]==outmax)
        {
            top--;
            ans[++cnt]=outmax;    
            outmax=maxs[i+1];
            while(s[top]>outmax)
                ans[++cnt]=s[top],top--;
        }    
    }    
    while(top)
    {ans[++cnt]=s[top];top--;}
    for(int i=1;i<=n;i++)
        printf("%d ",ans[i]);
    return 0;    
}
“Make my parents proud,and impress the girl I like.”
原文地址:https://www.cnblogs.com/NSD-email0820/p/9653293.html