Replace by MEX

Replace by MEX
在这里插入图片描述

  1. 题意:
    你被给予了一个数组,包含 n n n [ 0 , n ] [0, n] [0,n]的整数。每一次操作,你可以选择数组中的一个元素替换成这个数组的 M E X MEX MEX。例如,如果数组是 [ 0 , 2 , 2 , 1 , 4 ] [0, 2, 2, 1, 4] [0,2,2,1,4],你可以选择第二个元素替换成整个数组元素的 M E X MEX MEX,数组会变成 [ 0 , 3 , 2 , 1 , 4 ] [0, 3, 2, 1, 4] [0,3,2,1,4] M E X MEX MEX的定义为不包含这个于这个数组的最小的非负整数。

  2. 分析:
    每次计算当前的 M E X MEX MEX,如果 M E X = 0 MEX=0 MEX=0,则找任意一个 a [ i ] ≠ i a[i] \not =i a[i]=i a [ i ] a [ i] a[i]替换为 M E X MEX MEX使得 M E X MEX MEX不为 0 0 0,然后重新找MEX,更新 a [ M E X ] = M E X a [ M E X ] = M E X a[MEX]=MEX;否则直接更新 a [ M E X ] = M E X a [ M E X ] = M EX a[MEX]=MEX
    显然,对于第 i i i次操作, M E X MEX MEX要么等于 0 0 0,要么等于 i i i,因此第 i i i次操作至多更新两次,这就保证了操作次数至多 2 n 2n 2n次。

#include<bits/stdc++.h>

using namespace std;
const int maxn=1e3+10;
int a[maxn];
bool vis[maxn];
int n;

inline int f() {
    for (int i = 0; i <= n; i++) {
        vis[i] = false;
    }
    for (int i = 1; i <= n; i++) {
        vis[a[i]] = true;
    }
    for (int i = 0; i <= n + 1; i++) {
        if (!vis[i]) return i;
    }
}
vector<int>res;

inline void solve() {
    scanf("%d", &n);
    res.clear();
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    for (int i = 1; i <= n; i++) {
        int mex = f();
        if (!mex) {
            bool flag = false;
            for (int j = 1; j <= n; j++) {
                if (j != a[j]) {
                    a[j] = 0;
                    res.push_back(j);
                    flag = true;
                    break;
                }
            }
            if (!flag) break;
            mex = f();
        }
        a[mex] = mex;
        res.push_back(mex);
    }
    printf("%d\n", res.size());
    for (int i = 0; i < res.size(); i++) {
        printf("%d", res[i]);
        if (i == res.size() - 1) puts(""); else printf(" ");
    }
}

int main() {
    int _;
    scanf("%d", &_);
    while (_--) {
        solve();
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值