思路:
建立主席树,从后到前,如果有就将其拿到前面
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=200005;
struct node
{
int lc,rc,num;
} tree[maxn*40];
int cnt,rnu,now;
int a[maxn];
int num[maxn];
int root[maxn];
int has[1000005];
void build(int &i,int l,int r)
{
tree[++cnt]=tree[i];
i=cnt;
tree[i].num=0;
if(l==r)
return ;
int mid=(l+r)>>1;
build(tree[i].lc,l,mid);
build(tree[i].rc,mid+1,r);
}
void update(int &i,int l,int r,int w,int pos)
{
tree[++cnt]=tree[i];
i=cnt;
tree[i].num+=w;
if(l==r)
return ;
int mid=(l+r)>>1;
if(pos<=mid)
update(tree[i].lc,l,mid,w,pos);
else
update(tree[i].rc,mid+1,r,w,pos);
}
int query(int i,int nl,int nr,int l,int r )
{
if(l>=nl&&r<=nr)
return tree[i].num;
int mid=(l+r)>>1;
int ans=0;
if(nr>mid)
ans+=query(tree[i].rc,nl,nr,mid+1,r);
if(nl<=mid)
ans+=query(tree[i].lc,nl,nr,l,mid);
return ans;
}
int main()
{
memset(has,0,sizeof(has));
int n;
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",&num[i]),a[i]=num[i];
now=rnu=cnt=0;
root[n+1]=0;
build(root[n+1],1,n);
for(int i=n; i>=1; i--)
{
int tmp;
if(has[num[i]])
{
update(tmp=root[i+1],1,n,-1,has[num[i]]);
update(root[i]=tmp,1,n,1,i);
}
else
update(root[i]=root[i+1],1,n,1,i);
has[num[i]]=i;
}
int m;
scanf("%d",&m);
while(m--)
{
int l,r;
scanf("%d%d",&l,&r);
int ans=query(root[l],l,r,1,n);
printf("%d\n",ans);
}
}