题目传送门 ~~~
题目大意
有一个长度为 n 的数组 a
m 次询问,每次询问一个区间内最小没有出现过的自然数。
所有数据小于 2e5
思路
无修的区间查询,考虑莫队,好像可以写,因为只需要统计每个数字出现的次数,写了,交了,TIE /(ㄒoㄒ)/~~
思考,发现删除数据的时候 mex 特别容易维护,删掉一个数,这个数出现次数变为零,比较一下它会不会成为 mex 就好。
但是,增加数据的时候 mex 的维护就很麻烦,暴力找,稳TIE。
查了一下,说给值域进行分块就行了,这样维护mex的时间复杂度可以从 O(n) 降到 O(√n ),写了,交了,TIE /(ㄒoㄒ)/~~
再思考,之前维护mex是在add函数里边,仔细一想,是不是傻,干嘛每次add都去维护mex,最后记录答案的时候维护一下 mex 不就行了嘛,写了,交了, AC /(ㄒoㄒ)/~~
再再思考,好像就是这样,以后再写莫队的时候,就要考虑一下如何维护答案的时间复杂度会更优
AC代码
#include <bits/stdc++.h>
#include <stdio.h>
#include <vector>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#define ll long long
#define chushi(a, b) memset(a, b, sizeof(a))
#define endl "\n"
const double eps = 1e-8;
const ll INF=0x3f3f3f3f;
const int mod=1e9 + 7;
const int maxn = 2e5 + 15;
const int N=1005;
using namespace std;
int a[maxn], t[maxn], ANS = 0, ans[maxn];
int pos[maxn], R[maxn], L[maxn], tot = 0, cnt[maxn];
typedef struct Node{
int l, r;
int id;
} node;
int sqt;
inline bool cmp(node A, node B){
if(A.l/sqt == B.l/sqt) return A.l/sqt%2 == 1 ? A.r < B.r : A.r > B.r;
else return A.l/sqt < B.l/sqt;
}
node q[maxn];
inline void get_ANS(){
int ind = 1;
while(cnt[ind] == R[ind] - L[ind] + 1) ind++;
for(int i = L[ind]; i <= R[ind]; i++){
if(!t[i]){
ANS = i;
return;
}
}
}
inline void add(int num){
if((++t[num]) == 1) cnt[pos[num]]++;
}
inline void subd(int num){
if((--t[num]) == 0) cnt[pos[num]]--, ANS = min(ANS, num);
}
int main() {
int n, m;
scanf("%d %d", &n, &m);
sqt = sqrt(n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
for(int i = 0; i <= n; i++) pos[i] = i / sqt + 1;
for(int i = 0; i <= n; i += sqt) L[++tot] = i, R[tot] = i + sqt - 1;
for(int i = 1; i <= m; i++) scanf("%d %d", &q[i].l, &q[i].r), q[i].id = i;
sort(q+1, q+1+m, cmp);
for(int l = 1, r = 0, i = 1; i <= m; i++){
int ln = q[i].l, rn = q[i].r;
while(l < ln) subd(a[l++]);
while(l > ln) add(a[--l]);
while(r < rn) add(a[++r]);
while(r > rn) subd(a[r--]);
if(t[ANS]) get_ANS();
ans[q[i].id] = ANS;
}
for(int i = 1; i <= m; i++) printf("%d\n", ans[i]);
return 0;
}