题目背景
SOURCE:NOIP2015-SHY-8
题目描述
给定一个元素个数为 n 的整数数组 a 和 Q 个问题,每个问题有 x,y 两个参数,请统计共有多少个整数 K 满足 K 在 a[x]…a[y] 中出现了恰好 K 次。
输入格式
第一行两个整数 n,Q,表示数组 a 的元素个数和询问数;
接下来一行 n 给整数,描述数组 a ;
接下来 Q 行,每行两个数
xi
,
yi
(1≤
xi
≤
yi
≤n),表示询问的左右边界。
输出格式
输出 Q 行,每行一个整数表示满足询问的 K 的个数。
样例数据
输入
7 2
3 1 2 2 3 3 7
1 7
3 4
输出
3
1
备注
【样例说明】
Q1: 1、2、3 分别满足,所以共有 3 个数满足要求。
Q2: 2 满足,所以只有 1 个数满足要求。
【数据范围】
对 50% 的输入数据:1≤n,Q≤1000
对 100% 的输入数据:1≤n,Q≤100000,1≤a[i]≤
109
分析:这道题用莫队算法,什么是莫队算法呢,就是用前一个询问更新后一个,而这道题要分块,好处是把排序O(
n2
)降到了O(n
√
n)。将询问排序,一个询问计算出来之后与下一个询问左右边界比较,然后移动左右边界更新答案。
注意:若前一个询问l(或r)在后一个之外,那么就要从l开始更新;而如果在后一个之内,就要从l之前一个(r之后一个)更新。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#include<queue>
#include<set>
using namespace std;
int getint()
{
int sum=0,f=1;
char ch;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-')
{
f=-1;
ch=getchar();
}
for(;ch>='0'&&ch<='9';ch=getchar())
sum=(sum<<3)+(sum<<1)+ch-48;
return sum*f;
}
const int maxn=100010;
struct node{
int l,r,id,pos;
}q[maxn];
int n,Q,s,res;
int a[maxn],c[maxn],ans[maxn];
bool comp(const node &a,const node &b)
{
if(a.id==b.id)
return a.r<b.r;
return a.id<b.id;
}
int main()
{
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
n=getint();Q=getint();
for(int i=1;i<=n;++i)
{
a[i]=getint();
if(a[i]<=n) c[a[i]]++;
}
for(int i=1;i<=n;++i)
if(c[i]==i) res++;
s=(int)sqrt(n);
for(int i=1;i<=Q;++i)
{
q[i].l=getint(),q[i].r=getint();
q[i].id=q[i].l/s+1;
q[i].pos=i;
}
sort(q+1,q+Q+1,comp);
int l=1,r=n;
for(int i=1;i<=Q;++i)
{
while(l<q[i].l)
{
if(a[l]>n)
{
l++;
continue;
}
if(a[l]==c[a[l]]) res--;
if(a[l]==c[a[l]]-1) res++;
c[a[l]]--;
l++;
}
while(l>q[i].l)//边界
{
l--;
if(a[l]>n)
continue;
if(a[l]==c[a[l]]) res--;
if(a[l]==c[a[l]]+1) res++;
c[a[l]]++;
}
while(r>q[i].r)
{
if(a[r]>n)
{
r--;
continue;
}
if(a[r]==c[a[r]]) res--;
if(a[r]==c[a[r]]-1) res++;
c[a[r]]--;
r--;
}
while(r<q[i].r)//边界
{
r++;
if(a[r]>n)
continue;
if(a[r]==c[a[r]]) res--;
if(a[r]==c[a[r]]+1) res++;
c[a[r]]++;
}
ans[q[i].pos]=res;
l=q[i].l,r=q[i].r;
}
for(int i=1;i<=Q;++i)
cout<<ans[i]<<'\n';
return 0;
}
本题结。