洛谷-P4137 Rmq Problem / mex
阿新 • • 發佈:2022-05-28
Rmq Problem / mex
求區間的 MEX
回滾莫隊 模板題
不難發現,如果是刪除的話,只要判斷刪除的數字是否比當前的 MEX 小,然後更新就行;如果是增加的話,還要繼續往下遍歷才能得到結果,複雜度會很高
所以我們考慮回滾莫隊,只進行刪除操作
發現刪除操作比增加操作好寫很多
#include <iostream> #include <cstdio> #include <algorithm> #include <vector> #include <string> #include <queue> #include <functional> #include <map> #include <set> #include <cmath> #include <cstring> #include <deque> #include <stack> using namespace std; typedef long long ll; #define pii pair<int, int> const ll maxn = 2e5 + 10; const ll inf = 1e17 + 10; int num[maxn], last[maxn], pos[maxn]; int cnt[maxn], ans = 0, cnt_p[maxn]; struct node { int l, r, id; node(){} node(int _l, int _r, int _id){l = _l; r = _r; id = _id;} }seg[maxn]; bool cmp(const node& a, const node& b) { return pos[a.l] ^ pos[b.l] ? pos[a.l] < pos[b.l] : a.r > b.r; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, m; cin >> n >> m; for(int i=0; i<n; i++) cin >> num[i]; for(int i=0; i<m; i++) { int l, r; cin >> l >> r; l--; r--; seg[i] = node(l, r, i); } int t = max(1, (int)(n / sqrt(m))); for(int i=0; i<n; i++) pos[i] = i / t; sort(seg, seg + m, cmp); int l = 0, r = -1, pre_b = -1; for(int i=0; i<m; i++) { if(pos[seg[i].l] != pre_b) { pre_b = pos[seg[i].l]; for(int j=l; j<=r; j++) cnt[num[j]]--; l = pre_b * t; r = n - 1; for(int j=l; j<=r; j++) cnt[num[j]]++; for(int j=0; j<=n; j++) if(cnt[j] == 0) {ans = j; break;} } while(r > seg[i].r) { cnt[num[r]]--; if(cnt[num[r]] == 0) ans = num[r] < ans ? num[r] : ans; r--; } int way = ans, x = l; while(l < seg[i].l) { cnt[num[l]]--; if(cnt[num[l]] == 0) ans = num[l] < ans ? num[l] : ans; l++; } last[seg[i].id] = ans; for(int j=x; j<l; j++) cnt[num[j]]++; ans = way; l = x; } for(int i=0; i<m; i++) cout << last[i] << endl; return 0; }