SDOI2009 HH的项链 题解

建议:不要去洛谷交这题,放在这里只是告诉大家洛谷有这题莫队被卡掉了。

考虑莫队。

将点进行分块,将询问进行排序,按序处理每个询问,并使用 (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;
}
少说话,多做事。 ——cnyz 留
原文地址:https://www.cnblogs.com/lajiccf/p/12900480.html