莫队–最简单入门题
链接: https://www.spoj.com/problems/DQUERY/en/.
Given a sequence of n numbers a1, a2, …, an and a number of d-queries. A d-query is a pair (i, j) (1 ≤ i ≤ j ≤ n). For each d-query (i, j), you have to return the number of distinct elements in the subsequence ai, ai+1, …, aj.
Input
Line 1: n (1 ≤ n ≤ 30000).
Line 2: n numbers a1, a2, …, an (1 ≤ ai ≤ 106).
Line 3: q (1 ≤ q ≤ 200000), the number of d-queries.
In the next q lines, each line contains 2 numbers i, j representing a d-query (1 ≤ i ≤ j ≤ n).
Output
For each d-query (i, j), print the number of distinct elements in the subsequence ai, ai+1, …, aj in a single line.
Example
Input
5
1 1 2 1 3
3
1 5
2 4
3 5
Output
3
2
3
题意:找询问区间里不同数的个数。
模板题,代码如下
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=1000006;
int n,m,a[maxn],b[maxn],cnt[maxn],ans[maxn];
int l=1,r=0,sum=0;
struct fun
{
int l;
int r;
int id;
}mo[maxn];
bool cmp(fun x,fun y)//分块的排序,同一块就按r排序,否则按l排序
{
if(b[x.l]==b[y.l])
return x.r <y.r ;
else return x.l<y.l;
}
void add(int pos)
{
if(cnt[a[pos]]==0)
sum++;
cnt[a[pos]]++;
}
void del(int pos)
{
cnt[a[pos]]--;
if(cnt[a[pos]]==0)
sum--;
}
int main()
{
scanf("%d",&n);
int size=sqrt(n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=i/size+1;
}
scanf("%d",&m);
for(int i=0;i<m;i++)
{
scanf("%d %d",&mo[i].l ,&mo[i].r);
mo[i].id =i;
}
sort(mo,mo+m,cmp);
l=1,r=0;
for(int i=0;i<m;i++)
{
while(l>mo[i].l )//同一块里面
{
add(l-1);//
l--;
}
while(l<mo[i].l )
{
del(l);
l++ ;
}
while(r<mo[i].r)
{
add(r+1);//
r++;
}
while(r>mo[i].r)//不在同一块
{
del(r);
r--;
}
ans[mo[i].id]=sum;
}
for(int i=0;i<m;i++)
{
cout<<ans[i]<<endl;
}
}