莫队+值域分块
莫队有(O(nsqrt{n}))次修改,(O(m))次查询,就不能用(O(logn))修改与查询的线段树。而是用(O(1))修改,(O(sqrt{n}))查询的值域分块。同时(a_i>n)的数可以忽略。
复杂度(O((n+m)sqrt{n}))
#define B cout << "BreakPoint" << endl;
#define O(x) cout << #x << " " << x << endl;
#define O_(x) cout << #x << " " << x << " ";
#define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
#define LL long long
const int inf = 1e9 + 9;
const int N = 2e5 + 5;
using namespace std;
inline int read() {
int s = 0,w = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-')
w = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9') {
s = s * 10 + ch - '0';
ch = getchar();
}
return s * w;
}
int n,m,block,tmp[N],a[N],c[N],bl[N],ans[N];
struct node {
int l,r,v;
bool operator < (const node &x) const {
return bl[l] == bl[x.l] ? r > x.r : l < x.l;
}
}t[N];
void add(int x) {
if(x <= n) tmp[bl[x]] += !c[x]++;
}
void del(int x) {
if(x <= n) tmp[bl[x]] -= !--c[x];
}
void init(){
n = read(),m = read();
block = sqrt(n);
for(int i = 1;i <= n;i++) a[i] = read(),bl[i] = (i - 1) / block + 1;
for(int i = 1;i <= m;i++) t[i].v = i,t[i].l = read(), t[i].r = read();
sort(t + 1,t + m + 1);
return ;
}
void solve(){
int l = 1,r = 0;
for(int i = 1; i <= m; i++) {
while(l > t[i].l) add(a[--l]);
while(r < t[i].r) add(a[++r]);
while(l < t[i].l) del(a[l++]);
while(r > t[i].r) del(a[r--]);
if(!c[0]) continue;
int res = 1;
while(tmp[res] == block) res++;
res = (res - 1) * block + 1;
while(c[res]) res++;
ans[t[i].v] = res;
}
for(int i = 1;i <= m;i++) printf("%d
", ans[i]);
return ;
}
int main() {
init();
solve();
return 0;
}