题意:
给你一个数列,每次删除所有a[i]. a[i]满足, a[i]<=a[i-1] || a[i]>=a[i+1],
从而获得一个新数列,如果新数列还有这样的数,重复以上操作。
直到数列成为单调递增为止。
题解:
很容易想到链表模拟,但是直接一遍一遍扫肯定tle
然后可以发现,每次删掉一个数之后,受影响的只有他之前和他之后的两个数。
所以,我们可以用两个队列,一个保存当前剩余的数有哪些,另一个保存,上次删除的数的上一个数是那些:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+10;
const int eps=1e-4;
int n,x,cnt;
int pre[maxn],nxt[maxn],num[maxn],ans[maxn];
queue<int>que,tque;
void init(){
cnt=0;
while(!que.empty()) que.pop();
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&x);
num[++cnt]=x;
pre[cnt]=cnt-1;
nxt[cnt]=cnt+1;
que.push(i);
}
num[0]=0;nxt[0]=1;
num[++cnt]=maxn;
pre[cnt]=cnt-1;
nxt[cnt]=cnt+1;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
init();
while(1){
int t,y,z,f;
while(!tque.empty()) tque.pop();
while(!que.empty()){
t=que.front();
que.pop();
y=nxt[t];
z=num[t];
f=0;
while(y!=cnt&&z>num[y]){
z=num[y];
y=nxt[y];
f=1;
}
if(f){
pre[y]=pre[t];
nxt[pre[t]]=y;
tque.push(pre[t]);
while(!que.empty()&&que.front()<y)
que.pop();
}
}
if(tque.size()==0) break;
while(!tque.empty()){
que.push(tque.front());
tque.pop();
}
}
int s=0,p=0;
while(s!=cnt){
if(s!=0)
ans[++p]=num[s];
s=nxt[s];
}
printf("%d\n",p);
for(int i=1;i<=p;++i)
printf("%d ",ans[i]);
puts("");
}
return 0;
}