Codeforces Round #136 (Div. 2) D. Little Elephant and Array 线段树 离线处理

D. Little Elephant and Array
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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.

Input

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).

Output

In m lines print m integers — the answers to the queries. The j-th line should contain the answer to the j-th query.

Sample test(s)
Input
7 2
3 1 2 2 3 3 7
1 7
3 4
Output
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;
}


你可能感兴趣的:(Codeforces Round #136 (Div. 2) D. Little Elephant and Array 线段树 离线处理)