>Description
>Input
>Output
>Sample Input
5
1 4 3 5 2
>Sample Output
1 2 4 3 5
>解题思路
用三个指针 l、r、keyl 指向a数组,位置l~ r表示是已经入了栈的,keyl~n是等待入栈的数。
a数组不用进行预先处理,l为栈底,r为栈顶。每次要存入一个数到b数组(答案里),就找到keyl~n中最小的数,如果l<=r的话,再与 al 和ar进行比较取最小的值(因为栈底和栈顶的数都可以直接弹出),把最小的值记录到b数组里,还要标记此数已被取,同时把 r 和 keyl 更新,如果最小的数在keyl~n中的话(位置为s吧),就把 r 更新为s-1,keyl为s+1。接着继续循环。
但是每次都要枚举找keyl~n中最小的数的话会超时,所以这里要植入ST表。
>代码
#include<iostream>
#include<cstdio>
using namespace std;
int n,c,l,r,keyl,a[100005],b[100005],stu[100005][20],st[100005][20],ll[100005];
bool yd[100005];
int main()
{
// freopen("stack.in","r",stdin);
// freopen("stack.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int k=0;k<=20;k++)
for(int i=1;i+(1<<k)-1<=n;i++)
if(k==0) stu[i][k]=a[i],st[i][k]=i;
else
{
int x=stu[i][k-1],y=stu[i+(1<<(k-1))][k-1];
if(x<y) stu[i][k]=x,st[i][k]=st[i][k-1];
else stu[i][k]=y,st[i][k]=st[i+(1<<(k-1))][k-1];
} //ST表,stu记录最小值,st记录最小值的位置
ll[0]=-1;
for(int i=1;i<=n;i++)
ll[i]=ll[i>>1]+1; //这个在使用ST表的时候要用到
l=keyl=1;
for(int i=1;i<=n;i++)
{
int p=100000,pp=0;
if(keyl<=n)
{
int x=stu[keyl][ll[n-keyl+1]],y=stu[n-(1<<ll[n-keyl+1])+1][ll[n-keyl+1]];
if(x<y) p=x,pp=st[keyl][ll[n-keyl+1]];
else p=y,pp=st[n-(1<<ll[n-keyl+1])+1][ll[n-keyl+1]];
}
if(l<=r)
{
if(a[l]<p) p=a[l],pp=l;
if(a[r]<p) p=a[r],pp=r;
} //上文有详细解释
b[i]=p; yd[pp]=1;
r=max(r,pp-1); keyl=max(keyl,pp+1); //更新(注意要max一下)
while(yd[l]) l++;
while(yd[r]) r--; //不计算已经记录过的数
}
for(int i=1;i<=n;i++)
printf("%d ",b[i]);
return 0;
}