【问题描述】
Beerus需要对n个整数的数组进行排序。他可以同时销毁数组中所有未排序的整数。如果满足以下要求,则整数A[i]是有序的:
① A[i]是数组的第一个元素,或者不小于左边的A[i-1]。
② A[i]是数组的最后一个元素,或者不大于右边的A[i+1]。
例如,在{1,4,5,2,3}中,Beerus可以销毁5和2,该数组将变为{1,4,3}。如果新数组仍未排序,Beerus可以再次进行销毁。
请你帮助Beerus预测最终的数组。采用队列求解。
【输入形式】
每个测试用例,第一行提供初始数组的大小,该大小应为正且不大于100000。第二行描述具有n个正整数A[1],A[2],⋯,A[n]的数组,其中每个整数A[i]满足1≤A[i]≤100000。
【输出形式】
对于每个测试用例输出两行,第一行包含一个整数m,它是最终数组的大小。第二行包含m个描述最终数组的整数(每个整数之后空一格)。如果最后一个数组为空,则输出0,第二行为空行。
【样例输入】
5
1 2 3 4 5
5
5 4 3 2 1
5
1 2 3 2 1
【样例输出】
5
1 2 3 4 5
0
2
1 2
【思路】
用无穷和负无穷将两个端点情况转化为一般情况;
用一个长度为2的缓存队列,去存放检查元素和检查元素前一个元素,q去取后一个元素,
每次循环,先判断当前元素是否有序,再将该元素移至缓存队列头部,设立标志flagxu,判断是否入有序栈qsor,最后将有序栈中元素重新放入q中开始下一次检查;
【代码】
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define maxsize 100000
#define inf 100005
using namespace std;
queue <int> q;
queue <int> qsor;
queue <int> qche;//用缓存队列实现对前面元素的访问
int a[maxsize];//存放所有成员,大数组定义在主函数外
void sort_des(int a[],int n){
q.push(-10);
for (int i=0;i<n;i++){
q.push(a[i]);
}//初始化
q.push(inf);
if(n <=0){
cout<<"n输入错误\n";
return;
}
if(n==1){
cout<<n<<endl<<a[0];
return;
}
int flag=1;
while(flag>0){
qche.push(q.front());//缓存队列初始化
q.pop();
qche.push(q.front());
q.pop();
int flagxu=1;
while(!q.empty()){
if(qche.front()<=qche.back() && qche.back()<=q.front()){//判断缓存队列尾部是否有序
flagxu=1;
}
else{
flag=2;//标志出现无序数,需要再一次循环
flagxu=0;
}
qche.pop();
qche.push(q.front());//原尾部元素移至头部
q.pop();
if (flagxu==1){//上一次检查的是当前缓存队列头部元素
qsor.push(qche.front());//flagxu表示上一次检查有序,故上一个数存入qsor
}
}
qche.pop();
qche.pop();//此时缓存队列中为数组最后一个数和 inf,其有序已验证 ,清空缓存
q.push(-10);
while(!qsor.empty()){
q.push(qsor.front());
qsor.pop();
}
q.push(inf);
flag--;
}
memset(a,0,sizeof(int)*maxsize);
int j=0;
q.pop();//除去头
while(!q.empty()){
a[j]=q.front();
q.pop();
j++;
}
cout<<j-1<<endl;//末尾无穷再除去
for (int i=0;i<j-1;i++){
cout<<a[i]<<" ";
}
}
int main(){
int n;
freopen("in.txt","r",stdin);
scanf("%d",&n);
memset(a,0,sizeof(int)*maxsize);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
sort_des(a,n);
return 0;
}