Description
HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH不断地收集新的贝壳,因此, 他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同 的贝壳?这个问题很难回答。。。因为项链实在是太长了。于是,他只好求助睿智的你,来解 决这个问题。
Input
第一行:一个整数N,表示项链的长度。 第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。 第三行:一个整数M,表示HH询问的个数。 接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。
Output
M行,每行一个整数,依次表示询问对应的答案。
Sample Input
6
1 2 3 4 3 5
3
1 2
3 5
2 6
Sample Output
2
2
4
HINT
对于20%的数据,N ≤ 100,M ≤ 1000;
对于40%的数据,N ≤ 3000,M ≤ 200000;
对于100%的数据,N ≤ 50000,M ≤ 200000。
先mark一下莫队算法(不会)。
说一下我的理解吧。
这里只涉及区间查询有多少个不同值的运算,没有涉及其他修改的操作,我们可以采取离线做法。
首先呢,我们按右边界点排序(方便操作).
然后我们记录用last[i]记录某个数字最后出现的位置,pre[i]记录某个数字之前是否有出现过,没出现过则为0.
这里我们主要以某个数字的第一次出现的点代表该数字(之后无论出现多少次都以第一次出现的该数字为主).
我们从1开始算,即(1~500000,从1算到500000),这里我们只需要统计到当前所给最大的右边界就行了(1~maxR)。
[l,r]如果多次出现某个相同的数字(并且在l之前从未出现过这个数字即pre[i]=0),我们就以第一个该数字为主(肯定在l之前被统计,这就是为什么最后统计的是左边界就好了).
----扫描左端点--------------------------------------------
总结:离线做法
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-12;
const int maxn = 50010;
const int maxm = 200010;
using namespace std;
inline int read(){
int x(0),f(1);
char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int N,M;
int last[1000010],pre[1000010];
int sum[maxn],ans[maxm];
struct Sq{
int l,r,pos;
bool operator<(const Sq&t)const{
return r<t.r;
}
}sq[maxm];
inline void update(int i,int val)
{
while(i<=N){
sum[i]+=val;
i+=lowbit(i);
}
}
inline int query(int i)
{
int res=0;
while(i){
res+=sum[i];
i-=lowbit(i);
}
return res;
}
void solve()
{
int t;
N=read();
mes(last,0);
for(int i=1;i<=N;++i){
t=read();
pre[i]=last[t];
last[t]=i;
}
M=read();
for(int i=1;i<=M;++i){
sq[i].l=read(),sq[i].r=read();
sq[i].pos=i;
}
stable_sort(sq,sq+M+1);
/* for(int i=1;i<=M;++i){
cout<<sq[i].l<<" "<<sq[i].r<<endl;
}*/
int cur=0;
for(int i=1;i<=M;++i){
while(cur<sq[i].r){
++cur;
update(pre[cur]+1,1);
update(cur+1,-1);
}
ans[sq[i].pos]=query(sq[i].l);
}
for(int i=1;i<=M;++i){
printf("%d\n",ans[i]);
}
}
int main()
{
//fin;
solve();
}