因为在线不太可搞,所以考虑离线。
首先,按照莫队的方式对操作排序,对权值分块,维护一下每个块出现的个数。
每次询问,找到第一个没有铺满的块,在下一个块内暴力找即可。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#define maxn 200010
using namespace std;
struct yts
{
int l,r,id;
}q[maxn];
int ans[maxn];
int pos[maxn],bel[maxn],L[maxn],R[maxn],w[maxn];
int num[maxn];
int a[maxn];
int n,m,tot,block,mx;
bool cmp(yts x,yts y)
{
if (pos[x.l]!=pos[y.l]) return x.l<y.l;
return x.r<y.r;
}
int query()
{
int i;
for (i=1;i<=tot;i++) if (num[i]!=block) break;
int j;
for (j=L[i];j<=R[i];j++) if (!w[j]) break;
return j;
}
void del(int x)
{
if (x>n) return;
w[x]--;
if (w[x]==0) num[bel[x]]--;
}
void add(int x)
{
if (x>n) return;
if (w[x]==0) num[bel[x]]++;
w[x]++;
}
void solve()
{
int l=1,r=0;
for (int i=1;i<=m;i++)
{
while (l<q[i].l) del(a[l++]);
while (r>q[i].r) del(a[r--]);
while (l>q[i].l) add(a[--l]);
while (r<q[i].r) add(a[++r]);
ans[q[i].id]=query();
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
block=(int)sqrt(n);
for (int i=1;i<=n;i++) pos[i]=(i-1)/block+1;
tot=n/block+1;
for (int i=0;i<=n;i++)
{
bel[i]=i/block+1;
if (!L[bel[i]]) L[bel[i]]=i;
R[bel[i]]=i;
}
L[1]=0;
for (int i=1;i<=m;i++) {scanf("%d%d",&q[i].l,&q[i].r);q[i].id=i;}
sort(q+1,q+m+1,cmp);
solve();
for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
return 0;
}