D. Replace by MEX(思维,暴力)

题目
在这里插入图片描述
Example
input
5
3
2 2 3
3
2 1 0
7
0 7 3 1 3 7 7
9
2 0 1 1 2 4 4 2 0
9
8 4 7 6 1 2 3 0 5
output
0

2
3 1
4
2 5 5 4
11
3 8 9 7 8 5 9 6 4 1 2
10
1 8 1 9 5 2 4 6 3 7
在这里插入图片描述

大致翻译:
给定了一个0到n(含0和n)之间的n个整数数组。
在一个操作中,可以选择数组的任何元素,并用数组元素的MEX替换它(该操作后可能会更改)。
例如,如果当前数组是[0,2,2,1,4],则可以选择第二个元素并用当前元素的MEX-3替换它。数组将变为[0,3,2,1,4]。
必须使数组不递减,最多使用2n个操作。
可以证明这总是可能的。请注意,您不必最小化操作数。如果有许多解决方案,您可以打印其中任何一个。
当且仅当b1≤b2≤…≤bn时,数组b[1…n]是非减的。
数组的MEX(minimum excluded)是不属于该数组的最小非负整数。例如:
[2,2,1]的MEX为0,因为0不属于数组。
[3,1,0,1]的MEX是2,因为0和1属于数组,而2不属于数组。
[0,3,1,2]的MEX是4,因为0、1、2和3属于数组,而4不属于数组。
值得一提的是,长度为n的数组的MEX总是介于0和n之间(包括0和n)。
输入
第一行包含一个整数t(1≤t≤200)-测试用例数。测试用例的描述如下。
每个测试用例的第一行包含数组的单个整数n(3≤n≤1000)-长度。
每个测试用例的第二行包含n个整数a1,…,数组的(0≤ai≤n)-元素。请注意,它们不必是不同的。
保证所有测试用例的n之和不超过1000。
输出
对于每个测试用例,必须输出两行:
第一行必须包含一个整数k(0≤k≤2n)-执行的操作数。
第二行必须包含k整数x1,…,xk(1个小于席席)n,其中Xi是选择用于第i个运算的索引。
如果有很多解决方案,你可以找到其中任何一个。请记住,不需要最小化k。
注意
在第一个测试用例中,数组已经是非递减的(2≤2≤3)。
第二个测试用例的说明(每个操作修改的元素用红色表示):
a=[2,1,0];初始MEX为3。
a=[2,1,3];新的MEX为0。
a=[0,1,3];新的MEX是2。
最后的数组是非递减的:0≤1≤3。
第三个测试用例的说明:
a=[0,7,3,1,3,7,7];初始MEX为2。
a=[0,2,3,1,3,7,7];新的MEX是4。
a=[0,2,3,1,4,7,7];新的MEX是5。
a=[0,2,3,1,5,7,7];新的MEX是4。
a=[0,2,3,4,5,7,7];新的MEX是1。
最后的数组是非递减的:0≤2≤3≤4≤5≤7≤7
思路:由题意得不需要最简步骤的方法,所以暴力就好
按顺序填,把n+1个数填到n个格子里,直接a[i]=i;
若当前mex为n则令a[n-1]=n,n–,之后只需考虑前n-1个格子……以此类推
所以数组里的数为i或i+1,且每种操作只一次,不会超过2n次操作

#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define eps 1e-6
typedef long long ll;
int a[1010],vis[1010],n;
int find(){
	memset(vis,0,sizeof(vis));
	for(int i=0;i<n;i++) vis[a[i]]=1;
	int mex=n;
	for(int i=0;i<n;i++)
		if(!vis[i]) return i;
	return mex;
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int pos=1;
		scanf("%d",&n);
		for(int i=0;i<n;i++){
			scanf("%d",&a[i]);
			if(i>0&&a[i]<a[i-1]) pos=0;
		}
		if(pos) printf("0\n\n");
		else{
			vector<int>ans;
			while(n>0){
				int mex=find();
				if(mex==n){
					a[n-1]=n;
					ans.push_back(n-1);
					n--;
				}else{
					a[mex]=mex;
					ans.push_back(mex);
				}
			}
			printf("%d\n",ans.size());
			for(int i=0;i<ans.size();i++){
				printf("%d ",ans[i]+1);
			}
			printf("\n");
		}
	}
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值