Ehab and Prefix MEXs(STL, 思維,模擬)
阿新 • • 發佈:2020-09-18
Ehab and Prefix MEXs
原題連結:傳送門
題目大意
給定一個數組a,長度為n,要求你找到一個數組b滿足:
對於每一個 \(a_i = MEX(\{b_1 , b_2,...b_n\})\),
MEX 運算表示不在集合中的最小的非負整數。
分析
做的時候突然沒有思路,現在理一下思路和做法。
首先先觀察找規律,如果要在b[i] 上放一個元素,那麼這個元素一定不在a[i]~a[n]中出現過,否則在後面就會產生矛盾。
那麼我們可以用一個set集合,將所有從i位置以後(包括i)沒有在a中出現過的數字存下來。每一次必然從這個set中取出一個數字存入陣列b中再將這個數從set中刪除。
我們來推裡一下這個方法為什麼是正確的:
首先如果對於 a[i-1] 成立的話,對於a[i],0~a[i]-1中一定已經被填滿了,因為a[i] <= i,前面填了 i - 1 個數子,b又是按照從小到大的順序儲存的,所以只要b取a[i-1]即可滿足條件。
如果a[i] == a[i-1] 時,那麼繼續取set中的第一個數即可。
實際上對於該問題:a[i] <= i 就解決了不可能沒有解的情況
注意事項
認真分析,div2 C題一般都是STL的用法和一些基礎的貪心dp冷靜思考耐心觀察一般都可以做出來的 加油
AC 程式碼
AC code
void slove() { int n;cin >> n; vector<int> a(n); map<int,int> m; set<int> b; for(int i = 0;i < n ;i ++) { cin >> a[i];m[a[i]] = 1; } for(int i = 0;i <= 2 * n;i ++) { if(m[i] == 0)b.insert(i); } for(int i = 0;i < n ;i ++) { if(i && a[i] != a[i-1])b.insert(a[i-1]); cout << *b.begin() << " "; b.erase(*b.begin()); } }
標程/優秀程式碼
#include <bits/stdc++.h> using namespace std; int a[100005],b[100005]; bool ex[100005]; int main() { int n; scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); memset(b,-1,sizeof(b)); for (int i=1;i<=n;i++) { if (a[i]!=a[i-1]) { b[i]=a[i-1]; ex[b[i]]=1; } } ex[a[n]]=1; int m=0; for (int i=1;i<=n;i++) { while (ex[m]) m++; if (b[i]==-1) { b[i]=m; ex[m]=1; } printf("%d ",b[i]); } }