Codeforces Round #767 (Div. 2) C.Meximum Array
题意:
给出长度为 n 的数列a,现在要经过下面操作构造数列 b:
选出数列 a 中前 k 个数,将前 k 个数的 MEX 值插入到数列 b 末尾。然后删除 a 中的这前 k 个数。
问,如何操作使得构造的数列 b 的字典序最大?
思路:
为了使得字典序最大,就要每次都挑选当前整个数列 a 能够达到的最大 MEX 放到数列 b 后面。
同时,为了让 b 的长度尽可能长,从前往后走的过程中,走过的数只要能够构成最大 MEX 了,就退出。让下面的数再尽量产生更多的数。
所以:
从后往前维护当前位置到最后一个位置能够达到的最大 MEX 值。
从前往后走,如果走到当前位置发现达到了当前位置存储的最大 MEX 值,那么往后走就没有意义了,退出。
再重新往后走。
如何求一个数列每次加上当前位置后的 MEX 值呢?如果一个数出现过了,就将其标记下来。用一个指针mex表示到当前位置的 MEX 值。
#include <bits/stdc++.h>
using namespace std;
int T,a[200005],cnt[200005],st[200005],d[200005];
int main(){
cin>>T;
while(T--){
int n;
cin>>n;
int a[n+1];
memset(cnt,0,sizeof(cnt));
memset(st,0,sizeof(st));
for(int i=1;i<=n;i++){
cin>>a[i];
cnt[a[i]]++;
}
int index=0,res=0;
for(int i=1;i<=n;i++){
cnt[a[i]]--;
st[a[i]]++;
while(st[index]) index++;
if(cnt[index]==0){
d[res++]=index;
index=0;
memset(st,0,sizeof(st));
}
}
cout<<res<<endl;
for(int l=0;l<res;l++)
cout<<d[l]<<" ";
cout<<endl;
}
}

浙公网安备 33010602011771号