洛谷-P4137 Rmq Problem / mex
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;
}

浙公网安备 33010602011771号