daimayuan465. 訂單編號(set/並查集)
阿新 • • 發佈:2022-03-03
題意:
給定陣列 \(a[]\)。構造新陣列 \(b[]\),要求 \(b_i\ge a_i\),\(b_i\neq b_{1\sim i-1}\),且 \(b_i\) 儘量小。輸出新陣列。
\(1\le n \le 5e5,1\le a_i \le 1e9\)
思路:
法一:set存區間,二分
set存所有未使用的閉區間的兩個端點,按右端點從小到大排序。對於每個數 x,二分找右端點大於等於 x 的未使用區間,看要不要把區間裂成兩個
set存用過的區間也能做,但是要討論區間的合併,特別麻煩。
int n; set<PII> S; void ins(int l, int r) //防止l>r { if(l <= r) S.insert({r,l}); } main() { iofast; S.insert({2e9,0}); cin >> n; while(n--) { int x; cin >> x; auto it = S.lower_bound({x,0}); if(it->se <= x) ins(x+1,it->fi), ins(it->se,x-1); else x = it->se, ins(x+1,it->fi); S.erase(it), cout << x << ' '; } }
法二:雜湊+並查集(慢一點)
p[x] 存 x 所在的集合的右邊第一個未使用位置。
unordered_map<int, int> p; int get(int x) { return (!p[x] ? x : (p[x] = get(p[x])) ); } main() { iofast; int n; cin >> n; while(n--) { int x; cin >> x; x = get(x); cout << x << ' '; p[x] = x + 1; } }