- http://www.lydsy.com/JudgeOnline/problem.php?id=1878
- https://www.luogu.com.cn/problem/P1972
- https://www.spoj.com/problems/DQUERY/
建议:不要去洛谷交这题,放在这里只是告诉大家洛谷有这题莫队被卡掉了。
考虑莫队。
将点进行分块,将询问进行排序,按序处理每个询问,并使用 (L,R) 两个指针进行维护。
其实这个题更像莫队板子?
代码:
#include <bits/stdc++.h>
using namespace std;
int n,a[50010],m;
int L=1,R=0,bl;
struct node {
int l,r,num;
} q[200010];
bool cmp(node a,node b) {
return (a.l/bl)==(b.l/bl)?a.r<b.r:(a.l/bl)<(b.l/bl);//询问排序
}
int cnt[1000010],sum;
void add(int x) {
cnt[x]++;
if(cnt[x]==1)
sum++;//增加一个元素
}
void del(int x) {
cnt[x]--;
if(cnt[x]==0)
sum--;//减少一个元素
}
int ans[200010];
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for(int i=1;i<=m;i++)
scanf("%d %d",&q[i].l,&q[i].r),q[i].num=i;
bl=sqrt(n);
//printf("%d
",bl);
sort(q+1,q+m+1,cmp);
for(int i=1;i<=m;i++) {
//printf("now do %d
",q[i].num);
while(R<q[i].r) add(a[++R]);
while(R>q[i].r) del(a[R--]);
while(L<q[i].l) del(a[L++]);
while(L>q[i].l) add(a[--L]);//这是莫队的精髓,挪动左右端点
ans[q[i].num]=sum;
}
for(int i=1;i<=m;i++)
printf("%d
",ans[i]);
return 0;
}