[CF1375D] Replace by MEX - 構造
阿新 • • 發佈:2020-12-18
Description
給定一個長度為 \(n\) 的數列,可以進行不超過 \(2n\) 次操作,每次可以選擇一個位置,將它的值設為當前整個數列的 mex。構造一種操作方案,使得整個數列的值單調不降。
Solution
我們考慮將整個數列做成 \(0,1,2,...,n-1\) 的形式。我們給出一種構造方案使得能在不超過 \(2n\) 步內將任何一個序列做成這種形式。
當整個數列的 mex 小於 n 時,執行 A 類操作,即將 \(a[mex+1]\) 賦值為 \(mex\);否則,執行 B 類操作,任意找一個不滿足 \(a[i]=i-1\) 的位置,將 \(a[i]\) 賦值為 \(mex=n\)
顯然每一個 B 類操作後一定緊跟著一個 A 類操作,而一個 A 類操作會搞定一個位置,並且這個位置以後再也不會被操作到。
#include <bits/stdc++.h> using namespace std; #define int long long int Mex(vector<int> vec) { vector<int> tmp(vec.size() + 2, 0); for (auto i : vec) if (1ull * i < 1ull * vec.size()) tmp[i]++; int ans = 0; while (tmp[ans]) ++ans; return ans; } void solve() { int n; cin >> n; vector<int> a(n + 2, 0); for (int i = 1; i <= n; i++) cin >> a[i]; vector<int> ans; while (true) { vector<int> tmp; for (int i = 1; i <= n; i++) tmp.push_back(a[i]); int mex = Mex(tmp); if (mex == n) { int pos = 0; for (int i = 1; i <= n; i++) if (a[i] != i - 1) { pos = i; break; } if (pos) { a[pos] = n; ans.push_back(pos); } else { break; } } else { a[mex + 1] = mex; ans.push_back(mex + 1); } } cout << ans.size() << endl; for (int i : ans) cout << i << " "; cout << endl; } signed main() { ios::sync_with_stdio(false); int t; cin >> t; while (t--) { solve(); } return 0; }