有一列数,每次可以将当前数索引最小的一个放入栈中,或从栈底或栈顶取出一个数
依次排列取出的数使之形成一个新的序列,让这个序列的字典序最小
因为要字典序最小,那肯定是贪心的
每次,考虑能取出(就是让他进入序列)三种数
- 栈顶
- 栈底
- 目前还没入栈的数中的最小的,当然如果去这种数要把索引在他前面的没有入栈的数都入栈
然后就直接比较这三个数谁大谁小就行了,对于还没入栈的数我还用了个带删堆维护。。。。感觉麻烦点了
比较时细节上也有些麻烦,不过还好,整个题还是挺简单的
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<iomanip>
#include<cstring>
#define reg register
#define EN puts("")
inline int read(){
register int x=0;register int y=1;
register char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return y?x:-x;
}
#define N 100005
struct data{
int x,id;
};
inline int operator < (data a,data b){return a.x>b.x;}
struct Heap{
std::priority_queue<data>insert,deleted;
inline void push(data a){insert.push(a);}
inline void del(data a){deleted.push(a);}
inline data top(){
while(!deleted.empty()&&!insert.empty()&&deleted.top().x==insert.top().x) deleted.pop(),insert.pop();
if(insert.empty()) return (data){(int)2e9,0};
return insert.top();
}
inline void clear(){
while(!insert.empty()) insert.pop();
while(!deleted.empty()) deleted.pop();
}
}heap;
int n,a[N];
int stack[N];
int main(){int T=read();while(T--){
n=read();
for(reg int i=1;i<=n;i++) a[i]=read(),heap.push((data){a[i],i});
reg int left=0,right=-1,pos=1;
for(reg int i=1;i<=n;i++){
if(left<=right&&heap.top().x>stack[left]&&heap.top().x>stack[right]){
if(stack[left]<stack[right]) printf("%d ",stack[left++]);
else printf("%d ",stack[right--]);
}
else if(heap.top().x<std::min(stack[left],stack[right])||left>right){
int id=heap.top().id;
printf("%d ",heap.top().x);
heap.del((data){a[id],id});
while(pos<id){
stack[++right]=a[pos];
heap.del((data){a[pos],pos});
pos++;
}
pos++;
}
else{
if(stack[left]<stack[right]) printf("%d ",stack[left++]);
else printf("%d ",stack[right--]);
}
}
heap.clear();EN;
}
return 0;
}