1. 程式人生 > 實用技巧 >Codeforces-1375-D-Replace by MEX

Codeforces-1375-D-Replace by MEX

題意:

有一個長度為 n 的陣列 a, \(0 \le a_i \le n\) .

一次操作可以選擇陣列中的任何元素,並將其替換為陣列元素的MEX ( MEX是陣列中未出現的最小自然數 ) .

請找到一個能讓陣列非遞減的解決方案(保證運算元 2n 之內必有解決方案)。

思路:

保證運算元 2n 之內讓陣列最終變為 \([0,1,…,n−1]\) .(\(s[i] = i\)

每一次操作:遍歷陣列,找到MEX。

​ 如果 MEX < n ,就將它放到最終的位置上,即 s[MEX]。

​ 如果 MEX = n,就遍歷陣列,找一個沒有歸位的位置,即 \(s[i] != i\) 的位置。

這樣可以保證至多兩個操作,就可以使一個數字歸位。總運算元小於等於 2n。

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
int s[1003];
int getMex(int n)
{
    vector<int> a(n + 1, 0);
    for (int i = 0; i < n; ++i) a[s[i]] = 1;
    for (int i = 0; i <= n; ++i) if (a[i] == 0) return i;
}
int check(int n)
{
    for (int i = 0; i < n; ++i) if (s[i] != i) return i;
    return -1;
}
inline void solve()
{
    vector<int> ans;
    int n; cin >> n;
    for (int i = 0; i < n; ++i) cin >> s[i];
    while (check(n) != -1)
    {
        int mex = getMex(n), pos = mex;
        if (mex == n) pos = check(n);
        s[pos] = mex;
        ans.push_back(pos);
    }
    cout << ans.size() << endl;
    for (auto i : ans)
        cout << i + 1 << " ";
    cout << endl;
}

int main()
{
    int T = 1; cin >> T;
    for (int i = 1; i <= T; ++i) solve();
    return 0;
}