题解:CF2207E1 N-MEX (Constructive Version)
MaxBlazeResFire · · 题解
不难想到
注意为了满足
实现起来,维护
容易单指针做到线性。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define MAXN 200005
int n,a[MAXN],b[MAXN],vis[MAXN];
inline void clear(){
for( int i = 0 ; i <= n + 1 ; i ++ ) a[i] = b[i] = vis[i] = 0;
}
inline void solve(){
scanf("%lld",&n);
for( int i = 1 ; i <= n ; i ++ ) scanf("%lld",&a[i]),a[i] <= n ? vis[a[i]] ++ : 0;
if( a[1] != n && a[1] != n - 1 ){ puts("NO"); clear(); return; }
a[0] = b[0] = n;
for( int i = n - 1 ; i >= 0 ; i -- )
if( a[i] < a[i + 1] ){ puts("NO"); clear(); return; }
//S 维护 >a[i] 的 mex 集合
set<int> S;
for( int i = 0 ; i <= n ; i ++ ) if( !vis[i] ) S.insert( i );
for( int i = 1 ; i <= n ; i ++ ){
if( i == 1 || a[i] == a[i - 1] ){
if( !(int)S.size() ){ puts("NO"); clear(); return; }
b[i] = *S.rbegin(),S.erase( b[i] );
}
else{
b[i] = a[i] + 2;
}
}
for( int i = 0 ; i <= n + 1 ; i ++ ) vis[i] = 0;
for( int i = 1 ; i <= n ; i ++ ) vis[b[i]] ++;
int mex = 0; while( vis[mex] ) mex ++;
for( int i = n ; i >= 1 ; i -- ){
if( mex != a[i] ){ puts("NO"); clear(); return; }
vis[b[i]] --;
if( vis[b[i]] || b[i] > mex )
mex ++; while( vis[mex] ) mex ++;
}
puts("YES");
for( int i = 1 ; i <= n ; i ++ ) printf("%lld ",b[i]);
puts("");
clear();
}
signed main(){
int t; scanf("%lld",&t);
while( t -- ) solve();
return 0;
}