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; }