题目描述
HH 有一串由各种漂亮的贝壳组成的项链。HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH 不断地收集新的贝壳,因此,他的项链变得越来越长。
有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答…… 因为项链实在是太长了。于是,他只好求助睿智的你,来解决这个问题。
输入格式
一行一个正整数 nnn,表示项链长度。
第二行 nnn 个正整数 aia_iai,表示项链中第 iii 个贝壳的种类。
第三行一个整数 mmm,表示 HH 询问的个数。
接下来 mmm 行,每行两个整数 l,rl,rl,r,表示询问的区间。
输出格式
输出 mmm 行,每行一个整数,依次表示询问对应的答案。
输入输出样例
6 1 2 3 4 3 5 3 1 2 3 5 2 6
2 2 4
说明/提示
【数据范围】
对于 20%20\%20% 的数据,1≤n,m≤50001\le n,m\leq 50001≤n,m≤5000;
对于 40%40\%40% 的数据,1≤n,m≤1051\le n,m\leq 10^51≤n,m≤105;
对于 60%60\%60% 的数据,1≤n,m≤5×1051\le n,m\leq 5\times 10^51≤n,m≤5×105;
对于 100%100\%100% 的数据,1≤n,m,ai≤1061\le n,m,a_i \leq 10^61≤n,m,ai≤106,1≤l≤r≤n1\le l \le r \le n1≤l≤r≤n。
本题可能需要较快的读入方式,最大数据点读入数据约 20MB
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 50010,maxm = 200010;
int s[maxn],pos[maxn],val[maxn],Ans[maxm];
int n,m,block;
struct Mation{
int left,right,id;
}q[maxm];
bool cmp(const Mation &a,const Mation &b){
if( pos[a.left] != pos[b.left] ) return pos[a.left] < pos[b.left];
return pos[a.right] < pos[b.right];
}
void solve(){
int left = 0,right = 0,ans = 0;
for(int i=1;i<=m;i++){
while(left < q[i].left) if( --val[s[left++]] == 0) ans--;
while(left > q[i].left) if( val[s[--left]]++ == 0) ans++;
while(right < q[i].right) if( val[s[++right]]++ == 0) ans++;
while(right > q[i].right) if( --val[s[right--]] == 0) ans--;
Ans[q[i].id] = ans;
}
}
int main(){
cin>>n;
block = sqrt(n);
for(int i=1;i<=n;i++){
cin>>s[i];
}
cin>>m;
for(int i=1;i<=n;i++){
pos[i] = (i-1)/block+1;
}
for(int i=1;i<=m;i++){
scanf("%d %d",&q[i].left,&q[i].right);
q[i].id = i;
}
sort(q+1,q+m+1,cmp);
solve();
for(int i=1;i<=m;i++){
cout<<Ans[i]<<endl;
}
return 0;
}