区间 mex 问题
可以考虑一下 P2709 的做法。
先用莫队取下出现在 \([l_i,r_i]\) 的位置的数,存进树状数组,然后二分求得区间和 \(ask(x)=x\) 的最大 \(x\) 就是答案。
注意 \(0\) 不能加入树状数组,于是先给所有数加 \(1\)。
块长取 \(n^{0.55}\) 最佳。
#include<bits/stdc++.h>
using namespace std;
const int N = 200010; int n, m, cnt[N], in[N], a[N];
#define W while
struct BIT {
	int tr[N]; int lbt(int x) {return x & (-x);}
	void add(int x, int k) {for(; x < N; x += lbt(x)) tr[x] += k;}
	int query(int x) {int sum = 0; for(; x; x -= lbt(x)) sum += tr[x]; return sum;}
} B;
void add(int x) {if(!cnt[x]) B.add(x, 1); cnt[x]++;}
void del(int x) {if(cnt[x] == 1) B.add(x, -1); cnt[x]--;}
int ask() {
	int l = 1, r = N - 1, ans = 0;
	while(l <= r) {
//		cout << l << ' ' << r << '\n';
		int mid = l + r >> 1;
		if(B.query(mid) == mid) ans = mid, l = mid + 1;
		else r = mid - 1;
	}
	return ans;
}
struct Q {int l, r, id;} q[N]; int ans[N];
bool cmp(Q a, Q b) {return in[a.l] != in[b.l] ? a.l < b.l : a.r < b.r;}
int main() {
	ios::sync_with_stdio(0); cin >> n >> m;
	for(int i = 1; i <= n; i++) cin >> a[i], a[i]++; int len = pow(n, 0.55);
	for(int i = 1; i <= n; i++) in[i] = (i + len - 1) / len; int l = 1, r = 0;
//	for(int i = 1; i <= n; i++) cout << in[i] << ' '; cout << '\n';
	for(int i = 0; i < m; i++) cin >> q[i].l >> q[i].r, q[i].id = i; sort(q, q + m, cmp);
	for(int i = 0; i < m; i++) {
		W(r < q[i].r) add(a[++r]); W(r > q[i].r) del(a[r--]);
		W(l < q[i].l) del(a[l++]); W(l > q[i].l) add(a[--l]);
		ans[q[i].id] = ask();
	}
	for(int i = 0; i < m; i++) cout << ans[i] << '\n';
	return 0;
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号