分析:
听说主席树和莫队可以做,前者不想写,后者我不会...
我们考虑将询问离线,按照左端点排序,之后先处理好从1开始选的答案,之后枚举从1到n,之后依次删除nxt[i],添加nxt[nxt[i]],之后当询问左端点等于i的时候,更新答案。
附上代码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
#define N 1000005
int n,m,a[N],vis[N],nxt[N],sum[N];
int find(int x)
{
int ret=0;
for(int i=x;i;i-=i&-i)ret+=sum[i];
return ret;
}
void fix(int x,int c)
{
for(int i=x;i<N;i+=i&-i)sum[i]+=c;
}
struct node
{
int idx,l,r,ans;
}q[N];
bool cmp(const node &a,const node &b){return a.l<b.l;}
bool cmp1(const node &a,const node &b){return a.idx<b.idx;}
int main()
{
scanf("%d%*d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(vis[a[i]])nxt[vis[a[i]]]=i;
vis[a[i]]=i;
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);q[i].idx=i;
}
sort(q+1,q+m+1,cmp);
for(int i=1;i<=n;i++)
{
if(nxt[i])fix(nxt[i],1);
if(nxt[nxt[i]]) fix(nxt[nxt[i]],-1);
}
int h=1;
for(int i=1;i<=n;i++)
{
while(q[h].l==i)q[h].ans=find(q[h].r)-find(i-1),h++;
if(nxt[i])fix(nxt[i],-1);
if(nxt[nxt[i]])fix(nxt[nxt[i]],1);
}
sort(q+1,q+m+1,cmp1);
for(int i=1;i<=m;i++)
{
printf("%d\n",q[i].ans);
}
return 0;
}