【题解】CF1375D Replace by MEX

\(\color{purple}{Link}\)

\(\text{Solution:}\)

观察到题目要求操作次数不超过\(2n,\)且不必最小化操作次数,所以一定是构造题。

考虑将序列转化为\([0,1,...n-1].\)于是,有以下操作方法:

  • \(a_i=i-1\)时,不予操作。
  • \(a_i\not =i-1\)\(mex=n\)时,任选一个不满足上面条件的\(a_i\)令它\(=mex.\)
  • \(a_i\not=i-1\)\(mex\not =n\)时,将\(a_{mex+1}=mex\)即可。

观察可得,第二个操作每个数最多一次,第三个同样。所以操作次数不超过\(2n.\)

#include<bits/stdc++.h>
using namespace std;
int T,n,a[200010];
vector<int>v;
inline bool check(){
	for(int i=1;i<=n;++i)if(a[i]!=i-1)return false;
	return true;
}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);v.clear();
		for(int i=1;i<=n;++i)scanf("%d",a+i);
		while(!check()){
			for(int i=1;i<=n;++i){
				if(a[i]==i-1)continue;
				else{
					int vis[2001];
					fill(vis,vis+n+1,0);
					for(int j=1;j<=n;++j)vis[a[j]]++;
					int mex=0;while(vis[mex])mex++;
					if(mex==n){
						int p;
						for(int j=1;j<=n;++j){
							if(a[j]!=j-1){
								p=j;
								break;
							}
						}
						v.push_back(p);a[p]=mex;
					}
					else a[mex+1]=mex,v.push_back(mex+1);
					break;
				}
			}
		}
		cout<<(int)v.size()<<endl;
		for(int i=0;i<(int)v.size();++i)cout<<v[i]<<" ";
		cout<<endl;
	}
	return 0;
}
posted @ 2020-07-20 09:45  Refined_heart  阅读(125)  评论(0编辑  收藏  举报