考场上没有想到正确的姿势,我菜不成声。(然而据说读入优化可暴力艹过?)
看了看别人的题解,用双向链表维护删除数字后的序列,每次删掉一个数x,影响的只有nxt[x]和pre[x],于是删掉一个数后,把pre[x]再放到set中下一次判断pre[x]和nxt[x]是否出问题就行了。因为最多只删n个数,每个数只会添加进1个pre[x],所以每个数出现的复杂度为n,因为删除连续段的数后pre[x] 相同,于是我们用set判重,复杂度为O(nlogn)。
#include<cstdio>
#include<cstring>
#include<set>
#include<vector>
#define maxl 100010
#define inf 2000000001
using namespace std;
int n;
int a[maxl],nxt[maxl],pre[maxl];
vector <int> tmp;
set <int> st;
bool in[maxl];
inline int read()
{
int x=0;char ch=getchar();
while(ch<'0' || ch>'9') ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
void prework()
{
n=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
nxt[i]=i+1;pre[i]=i-1;
st.insert(i);in[i]=false;
}
nxt[0]=1;a[n+1]=inf;
}
void mainwork()
{
int x,l,prex,nxtx;
while(st.size())
{
tmp.clear();
set <int> :: iterator it;
for(it=st.begin();it!=st.end();it++)
{
x=(*it);
if(a[pre[x]]>a[x]) tmp.push_back(pre[x]),tmp.push_back(x);
if(a[x]>a[nxt[x]]) tmp.push_back(x),tmp.push_back(nxt[x]);
}
st.clear();l=tmp.size();
for(int i=0;i<l;i++)
{
x=tmp[i];
if(!in[x])
{
nxt[pre[x]]=nxt[x];
pre[nxt[x]]=pre[x];
st.insert(pre[x]);
in[x]=true;
}
}
}
}
void print()
{
int cnt=0;
for(int i=nxt[0];i<=n;i=nxt[i])
cnt++;
printf("%d\n",cnt);
for(int i=nxt[0];i<=n;i=nxt[i])
printf("%d ",a[i]);
printf("\n");
}
int main()
{
int t;
t=read();
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}