数据结构(莫队算法):HH的项链

时间:2023-03-09 17:34:53
数据结构(莫队算法):HH的项链

问题描述:
HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步
完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH不断地收集新的贝壳,因此,
他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同
的贝壳?这个问题很难回答。。。因为项链实在是太长了。于是,他只好求助睿智的你,来解
决这个问题。
输入格式:
第一行:一个整数N,表示项链的长度。
第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。
第三行:一个整数M,表示HH询问的个数。
接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。
输出格式:
M行,每行一个整数,依次表示询问对应的答案。
样例输入:
6
1 2 3 4 3 5
3
1 2
3 5
2 6
样例输出:
2
2
4
数据范围:
对于20%的数据,N ≤ 100,M ≤ 1000;
对于40%的数据,N ≤ 3000,M ≤ 200000;
对于100%的数据,N ≤ 50000,M ≤ 200000。

  

 #include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const int N=,M=,K=;
int num[K],hsh[K],a[N],n,Q,block,cnt;
int ql[M],qr[M],p[M],ans[M],tmp,tim;
bool cmp(int x,int y){
return (ql[x]-)/block!=(ql[y]-)/block?ql[x]<ql[y]:qr[x]<qr[y];
}
void Add(int x){
if(!num[x])tmp++;
num[x]++;
}
void Min(int x){
if(num[x]==)tmp--;
num[x]--;
}
int main(){
freopen("diff.in","r",stdin);
freopen("diff.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
cin>>n;
for(int i=,x;i<=n;i++){
cin>>x;
if(!hsh[x])hsh[x]=++cnt;
a[i]=hsh[x];
}
cin>>Q;
for(int i=;i<=Q;i++)
cin>>ql[i]>>qr[i],p[i]=i;
block=(int)sqrt(n+0.5);
sort(p+,p+Q+,cmp);
int l=,r=;
for(int i=;i<=Q;i++){
while(ql[p[i]]<l)Add(a[--l]);
while(ql[p[i]]>l)Min(a[l++]);
while(qr[p[i]]>r)Add(a[++r]);
while(qr[p[i]]<r)Min(a[r--]);
ans[p[i]]=tmp;
}
for(int i=;i<=Q;i++)
cout<<ans[i]<<"\n";
return ;
}