线段树离线处理(区间内出现k次的数有多少个)Codeforces Round #136 (Div. 2)

来源:互联网 发布:淘宝个人主页 编辑:程序博客网 时间:2024/04/29 14:51

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 ton. 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 integerslj andrj(1 ≤ lj ≤ rj ≤ n). For each querylj, rj the Little Elephant has to count, how many numbersx exist, such that number x occurs exactly x times among numbersalj, alj + 1, ..., arj.

Help the Little Elephant to count the answers to all queries.

Input

The first line contains two space-separated integers n andm (1 ≤ n, m ≤ 105) — the size of arraya and the number of queries to it. The next line containsn space-separated positive integers a1, a2,..., an(1 ≤ ai ≤ 109). Nextm lines contain descriptions of queries, one per line. Thej-th of these lines contains the description of thej-th query as two space-separated integerslj andrj(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 23 1 2 2 3 3 71 73 4
Output
31

跟hdu4358很像,只不过4358需要先把树形结构转化成线性的

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std;#define LL(x) (x<<1)#define RR(x) (x<<1|1)const int N=1e5+5;struct Query{    int st,ed,id;    Query(){}    Query(int a,int b,int c){st=a;ed=b;id=c;}    bool operator < (const Query &b)const    {        return ed<b.ed;    }};struct node{    int lft,rht,sum;    int mid(){return lft+(rht-lft)/2;}};struct Segtree{    node tree[N*4];    void build(int lft,int rht,int ind)    {        tree[ind].lft=lft;  tree[ind].rht=rht;        tree[ind].sum=0;        if(lft!=rht)        {            int mid=tree[ind].mid();            build(lft,mid,LL(ind));            build(mid+1,rht,RR(ind));        }    }    void updata(int pos,int ind,int valu)    {        tree[ind].sum+=valu;        if(tree[ind].lft==tree[ind].rht) return;        else         {            int mid=tree[ind].mid();            if(pos<=mid) updata(pos,LL(ind),valu);            else updata(pos,RR(ind),valu);        }    }    int query(int be,int end,int ind)    {        int lft=tree[ind].lft,rht=tree[ind].rht;        if(be<=lft&&rht<=end) return tree[ind].sum;        else         {            int mid=tree[ind].mid();            int sum1=0,sum2=0;            if(be<=mid) sum1=query(be,end,LL(ind));            if(end>mid) sum2=query(be,end,RR(ind));            return sum1+sum2;        }    }}seg;vector<int> pos[N];vector<Query> query;int data[N],cnt[N],res[N];int main(){    int n,m;    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++) scanf("%d",&data[i]);    for(int i=0;i<m;i++)    {        int a,b;        scanf("%d%d",&a,&b);        query.push_back(Query(a,b,i));    }    sort(query.begin(),query.end());    int ind=0;    seg.build(1,n,1);    for(int i=1;i<=n;i++)    {        int valu=data[i];        if(valu<=n)        {            cnt[valu]++;            pos[valu].push_back(i);            if(cnt[valu]>=valu)            {                if(cnt[valu]>valu)                     seg.updata(pos[valu][cnt[valu]-valu-1],1,-2);                if(cnt[valu]>valu+1)                     seg.updata(pos[valu][cnt[valu]-valu-2],1,1);                seg.updata(pos[valu][cnt[valu]-valu],1,1);            }        }        while(query[ind].ed==i&&ind<m)        {            res[query[ind].id]=seg.query(query[ind].st,query[ind].ed,1);            ind++;        }    }    for(int i=0;i<m;i++) printf("%d\n",res[i]);    return 0;}




0 0