The Little Elephant loves playing with arrays. He has array a, consisting of n positive integers, indexed from 1 to n. Let's denote the number with index i as ai.
Additionally the Little Elephant has m queries to the array, each query is characterised by a pair of integers lj and rj (1 ≤ lj ≤ rj ≤ n). For each query lj, rj the Little Elephant has to count, how many numbers x exist, such that number x occurs exactly x times among numbers alj, alj + 1, ..., arj.
Help the Little Elephant to count the answers to all queries.
The first line contains two space-separated integers n and m (1 ≤ n, m ≤ 105) — the size of array a and the number of queries to it. The next line contains n space-separated positive integers a1, a2, ..., an (1 ≤ ai ≤ 109). Next m lines contain descriptions of queries, one per line. The j-th of these lines contains the description of the j-th query as two space-separated integers lj and rj (1 ≤ lj ≤ rj ≤ n).
In m lines print m integers — the answers to the queries. The j-th line should contain the answer to the j-th query.
7 2 3 1 2 2 3 3 7 1 7 3 4
3 1
N个数M个询问l,r,输出区间[l,r]内出现次数和值相等的有多少个。
记录下询问,按r从小到大排序。
i从1到N循环,每次处理出r=i的询问。循环过程中用vector V[val]记录val出现的每个位置,cnt[val]记录当前val出现的次数。
如果cnt[val]>=val,说明从V[val][cnt[val]-val]这里到当前的i这个区间肯定是满足的,在线段树上把V[val][cnt[val]-val]这里加1,并且V[val][cnt[val]-val-1]以及之前的位置到i这个区间是不满足的,当前V[val][cnt[val]-val-1]是已经加过1的,V[val][cnt[val]-val]也加了1,但是V[val][cnt[val]-val-1]到i是不满足的,所以把V[val][cnt[val]-val-1]这个位置减2,相当于在V[val][cnt[val]-val-1]这里多减一个1,抵消V[val][cnt[val]-val]加的1。又因为V[val][cnt[val]-val-2]已经减过2,现在已经有V[val][cnt[val]-val-1]来抵消了,所以V[val][cnt[val]-val-2]不需要减2了,要再加上1。
#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<algorithm>
#define pi (4*atan(1.0))
typedef long long LL;
using namespace std;
const int MAXN=100010;
const int MAXNODE=4*MAXN;
int N,M,a[MAXN],ans[MAXN],cnt[MAXN];
vector<int> V[MAXN];
struct Query{
int l,r,id;
bool operator < (const Query& rhs) const{
return r<rhs.r;
}
};
vector<Query> pos;
struct SegmentTree{
int sum[MAXNODE];
void clear(){
memset(sum,0,sizeof(sum));
}
void update(int o,int L,int R,int pos,int v){
if(L>=R){
sum[o]+=v;
return;
}
int mid=L+(R-L)/2;
if(pos<=mid) update(o<<1,L,mid,pos,v);
else update(o<<1|1,mid+1,R,pos,v);
sum[o]=sum[o<<1]+sum[o<<1|1];
}
int query(int o,int L,int R,int ql,int qr){
if(ql<=L&&qr>=R) return sum[o];
int mid=L+(R-L)/2,ret=0;
if(ql<=mid) ret+=query(o<<1,L,mid,ql,qr);
if(qr>mid) ret+=query(o<<1|1,mid+1,R,ql,qr);
return ret;
}
}tree;
int main(){
freopen("in.txt","r",stdin);
while(scanf("%d%d",&N,&M)!=EOF){
for(int i=1;i<=N;i++) scanf("%d",&a[i]);
pos.clear();
for(int i=1;i<=N;i++) V[i].clear();
int l,r;
for(int i=0;i<M;i++){
scanf("%d%d",&l,&r);
pos.push_back((Query){l,r,i});
}
sort(pos.begin(),pos.end());
tree.clear();
memset(cnt,0,sizeof(cnt));
int k=0;
for(int i=1;i<=N;i++){
int val=a[i];
if(val<=N){
cnt[val]++;
V[val].push_back(i);
if(cnt[val]>=val){
tree.update(1,1,N,V[val][cnt[val]-val],1);
if(cnt[val]>val) tree.update(1,1,N,V[val][cnt[val]-val-1],-2);
if(cnt[val]>val+1) tree.update(1,1,N,V[val][cnt[val]-val-2],1);
}
}
while(pos[k].r==i&&k<M){
ans[pos[k].id]=tree.query(1,1,N,pos[k].l,pos[k].r);
k++;
}
}
for(int i=0;i<M;i++) printf("%d\n",ans[i]);
}
return 0;
}