https://www.nowcoder.com/acm/contest/139/J
树状数组:询问两端区间其中不同数字的个数,可以离线,可以复制区间使得两个区间变成一个区间上的询问。
莫队:同样是离线,对于这个题来说有些许暴力,不过问题不大。
树状数组:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+45;
#define INF 0x3f3f3f3f;
#define ll long long int
#define charmax(x,y) x=max(x,y)
#define charmin(x,y) x=min(x,y)
#define clr(x,p) memset(x,p,sizeof x)
int n,m;
struct node{
int u,v;int id,ans;}q[maxn];
int a[2*maxn];
int c[2*maxn];
int num[2*maxn];
int pos[2*maxn];
void add(int x,int p){for(int i=x;i<=n;i+=i&-i)c[i]+=p;}
int query(int x) {int ans=0;for(int i=x;i>0;i-=i&-i)ans+=c[i];return ans;}
int cmp(node a,node b){
return a.v<b.v;}
int cmp2(node a,node b){
return a.id<b.id;}
int main()
{
while(~scanf("%d %d",&n,&m)){
clr(c,0);clr(num,0);clr(pos,-1);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=n+1;i<=2*n;i++){
a[i]=a[i-n];
}
for(int i=1;i<=m;i++){
scanf("%d %d",&q[i].u,&q[i].v);
q[i].u+=n;
swap(q[i].u,q[i].v);
q[i].id=i;
}
n=n*2;
for(int i=1;i<=n;i++){
if(!num[a[i]]){
num[a[i]]=i;
}
else{
pos[i]=num[a[i]];
num[a[i]]=i;
}
}
sort(q+1,q+1+m,cmp);int cs=1;
for(int i=1;i<=n&&cs<=m;i++){
add(i,1);
if(pos[i]!=-1){
add(pos[i],-1);
}
while(i==q[cs].v&&cs<=m){
q[cs].ans=query(q[cs].v)-query(q[cs].u-1);
cs++;
}
}
//cout<<c[2]<<endl;
sort(q+1,q+1+m,cmp2);
for(int i=1;i<=m;i++){
printf("%d\n",q[i].ans);
}
}
return 0;
}