题面
众所周知,熟练掌握至少一种排序算法是参加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; }