(CodeForces - 220B)Little Elephant and Array(莫队)

本文讲解了如何使用莫尔斯队列(Mo's Algorithm)解决 CodeForces 220B 题目,涉及添加和删除操作对区间内特定数值出现次数的影响,并强调了处理大数和边界条件的方法。通过实例代码展示了如何实现 add 和 sub 函数及注意事项。
摘要由CSDN通过智能技术生成

题目链接:Little Elephant and Array - CodeForces 220B - Virtual Judge (ppsucxtt.cn)

题意就是先给我们n个数,然后给我们m个询问,每个询问包含两个数l和r,让我们求出区间[ l , r ]内满足x出现x次的数有多少个。

这显然是用莫队来求,他满足莫队的题目要求,莫队的题目模板比较固定,关于模板方面我就不多说了,我主要说一下他的add函数和sub函数以及一些注意事项。

首先说一下add函数,我们每次增加一个值x,就用cnt记录一下,如果增加后这个值在当前区间中出现了x次,说明原来是出现了x-1次,我们就可以对答案进行加1,如果我们增加后这个值在当前区间出现了x+1次,那么说明之前这个值在当前区间中出现了x次,这时候我们就要对答案就行减一处理。

下面来说一下sub函数,我们每次减少一个值,也用cnt记录一下,如果减少后这个值在当前区间中出现了x次,说明原来是出现了x+1次,我们就可以对答案进行加1,如果我们减少后这个值在当前区间出现了x-1次,那么说明之前这个值在当前区间中出现了x次,这时候我们就要对答案就行减一处理。

下面说一下注意事项,a数组的取值很大,但是我们稍微分析一下题目所求的数就可以知道满足题意的数一定是小于等于n的,所以当x大于n时,直接不做处理即可。

下面是代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
using namespace std;
const int N=1e5+10;
int a[N],cnt[N],ans,sum[N];
struct node{
	int id,pl,l,r;
}p[N];
bool cmp(node a,node b)
{
	if(a.pl!=b.pl) return a.pl<b.pl;
	return a.r<b.r;
}
void add(int x)
{
	if(x>100000) return ;//当x>100000时,不可能出现x个x
	cnt[x]++;
	if(cnt[x]==x) ans++;
	if(cnt[x]==x+1) ans--;
}
void sub(int x)
{
	if(x>100000) return ;//当x>100000时,不可能出现x个x
	cnt[x]--;
	if(cnt[x]==x) ans++;
	if(cnt[x]==x-1) ans--;
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	int pl=sqrt(n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&p[i].l,&p[i].r);
		p[i].id=i;
		p[i].pl=(p[i].l-1)/pl+1;
	}
	sort(p+1,p+m+1,cmp);
	int l=1,r=0;
	for(int i=1;i<=m;i++)
	{
		while(l<p[i].l)
		{
			sub(a[l]);
			l++;
		}
		while(l>p[i].l)
		{
			l--;
			add(a[l]);
		}
		while(r<p[i].r)
		{
			r++;
			add(a[r]);
		}
		while(r>p[i].r)
		{
			sub(a[r]);
			r--;
		}
		sum[p[i].id]=ans;
	}
	for(int i=1;i<=m;i++)
		printf("%d\n",sum[i]);
	return 0;
} 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值