这是一道模拟题,限定每次找到序列中所有的单调下降的连续的子串,然后删除掉,不断重复上述步骤,最后使得序列单调非降。
这里有一个重要的结论,就是说我在第一步去掉了[L,R]这个区间,那么在第二次的时候,只有a[L-1]和a[R+1]这两个数字有可能形成单调下降的子串(长度最大为2)。
举例说明:
序列:4 6 2 3 3 5 2 2 3
下标:1 2 3 4 5 6 7 8 9
这是初始序列,在第一步找单调下降的连续的子串的时候我们找到了两个区间
[2,3]和[6,7]
然后我们删除掉两个区间
变成了
序列:4 3 3 2 3
下标:1 4 5 8 9
然后我们接下来只需要考虑下b标为(1、4)和下标为(5、8)的元素
然后我们发现a[1] = 4 > a[4] = 3所以删除掉a[1]和a[4] 发现a[5] > a[8],所以删除掉a[5]和a[8]
之后序列变成
序列:3
下标:9
到这里就完成了。
所以这个题目的思路就是这的:
1.找出单调下降区间,放入vector1里面
2.把vector2清空。把vector1里面的区间依次拿出来,如果两个区间完全相邻或者重叠,则将他们合并成一个大区间,放入vector2里面去。
3.把vector1清空。对vector2里面的区间[L,R]依次拿出来,如果L > 1 && R < n && a[L-1] > a[R - 1],那么就L--,R++;然后把这个区间再次放入vector1里面去。
4.如果区间有变化,那么就转到第2步,否则执行第5步。
5.所有vector1里面的区间都是被删掉的,然后取补集就是答案。
代码:
#include
using namespace std;
int T,n;
const int maxn = 1e5+7;
typedef pair P;
int a[maxn];
vector vec[2];
int mark[maxn];
void init(){
memset(mark,0,sizeof(mark));
}
int main(){
scanf("%d",&T);
int cnt = 0;
while(T--){
vec[0].clear();
vec[1].clear();
init();
scanf("%d",&n);
for(int i = 0;i < n;i++){
scanf("%d",&a[i]);
}
int last = 0;
int len = 0;
int kk = 0;
for(int i = 1;i < n;i++){
if(a[i] < a[i-1]){
len++;
}
else{
if(len){
vec[0].push_back(make_pair(last,i-1));
kk++;
}
len = 0;
last = i;
}
}
if(len){
vec[0].push_back(make_pair(last,n-1));
kk++;
}
if(!kk){
printf("%d\n",n);
for(int i =0 ;i < n;i++){
printf("%d ",a[i]);
}
puts("");
continue;
}
int flag = 1;
while(flag){
flag = 0;
vec[1].clear();
P pre = vec[0][0];
for(int i = 1;i < vec[0].size();i++){
P now = vec[0][i];
if(pre.second + 1 >= now.first){
pre.second = now.second;
}
else{
vec[1].push_back(pre);
pre = now;
}
}
vec[1].push_back(pre);
vec[0].clear();
for(int i = 0;i < vec[1].size();i++){
P pp = vec[1][i];
if(pp.first > 0 && pp.second < n-1){
if(a[pp.first-1] > a[pp.second+1]){
flag = 1;
pp.first --;
pp.second ++;
}
}
vec[0].push_back(pp);
}
}
for(int i = 0;i < vec[1].size();++i){
P p = vec[1][i];
for(int i = p.first;i <= p.second;++i){
mark[i] = 1;
}
}
vector ans;
for(int i = 0;i < n;i++){
if(!mark[i]){
ans.push_back(a[i]);
}
}
printf("%d\n",ans.size());
for(int i = 0;i < ans.size();++i){
printf("%d ",ans[i]);
}
puts("");
}
return 0;
}
/*
1
7
4 4 4 3 3 3 2
1
5
1 2 3 2 1
*/