Hrbust 2054 Boring Counting (主席树+二分)

来源:互联网 发布:mac更新 进度条 编辑:程序博客网 时间:2024/04/29 20:31

Boring Counting

Time Limit: 3000 MS Memory Limit: 32768 K

Total Submit: 67(21 users) Total Accepted: 5(5 users) Rating: Special Judge: No

Description

In this problem you are given a number sequence P consisting of N integer and Pi is the ith element in the sequence. Now you task is to answer a list of queries, for each query, please tell us among [L, R], how many Pi is not less than A and not greater than B( L<= i <= R). In other words, your task is to count the number of Pi (L <= i <= R, A <= Pi <= B).

Input

In the first line there is an integer T (1 < T <= 50), indicates the number of test cases.

For each case, the first line contains two numbers N and M (1 <= N, M <= 50000), the size of sequence P, the number of queries. The second line contains N numbers Pi(1 <= Pi <= 10^9), the number sequence P. Then there are M lines, each line contains four number L, R, A, B(1 <= L, R <= n, 1 <= A, B <= 10^9)

Output

For each case, at first output a line ‘Case #c:’, c is the case number start from 1. Then for each query output a line contains the answer.

Sample Input
1
13 5
6 9 5 2 3 6 8 7 3 2 5 1 4
1 13 1 10
1 13 3 6
3 6 3 6
2 8 2 8
1 9 1 9

Sample Output
Case #1:
13
7
3
6
9

题意:问[l,r]内>=a&&<=b的数的个数。
题解:
所需技能:主席树+二分+离散化。
先建一颗主席树便于我们快速求区间[L,R](数据过大,需要离散化),然后二分找到离散化后>=ad的最小值和<=b的最大值,然后统计一下就好。
代码:

#include<stdio.h>#include<stdlib.h>#include<algorithm>#include<iostream>#include<vector>#include<map>#include<set>#include<math.h>#include<string.h>#define ll long longusing namespace std;const int N=60000;struct node{int l,r,sum;} T[N*40];int n,t,m,x,y,k,cnt,l,r,tmp,root[N],a[N];vector<int>p;int getid(int x){return lower_bound(p.begin(),p.end(),x)-p.begin()+1;};void update(int l,int r,int &x,int y,int pos){    T[++cnt]=T[y],T[cnt].sum++,x=cnt;    if(l==r) return;    int mid=(r+l)>>1;    if(pos<=mid) update(l,mid,T[x].l,T[y].l,pos);    else        update(mid+1,r,T[x].r,T[y].r,pos);}int query(int L,int R,int l,int r,int x,int y){    if(L<=l&&R>=r) return T[y].sum-T[x].sum;    int mid=(r+l)>>1;    int res=0;    if(L<=mid) res+=query(L,R,l,mid,T[x].l,T[y].l);    if(R>mid)  res+=query(L,R,mid+1,r,T[x].r,T[y].r);    return res;}int solo1(int x){    int l=0,r=tmp-1;    int ans=-1;    while(r>=l)    {        int mid=(r+l)>>1;        if(p[mid]>=x)        {            ans=mid;            r=mid-1;        }        else            l=mid+1;    }    return ans;}int solo2(int x){    int l=0,r=tmp-1;    int ans=-1;    while(r>=l)    {        int mid=(r+l)>>1;        if(p[mid]<=x)        {            ans=mid;            l=mid+1;        }        else            r=mid-1;    }    return ans;}int main(){    scanf("%d",&t);    for(int cas=1; cas<=t; cas++)    {        p.clear();        cnt=1;        memset(root,0,sizeof(root));        memset(T,0,sizeof(T));        printf("Case #%d:\n",cas);        scanf("%d%d",&n,&m);        for(int i=1; i<=n; i++) scanf("%d",&a[i]),p.push_back(a[i]);        sort(p.begin(),p.end()),p.erase(unique(p.begin(),p.end()),p.end());        tmp=p.size();        for(int i=1; i<=n; i++) update(1,n,root[i],root[i-1],getid(a[i]));        for(int i=1; i<=m; i++)        {            scanf("%d%d%d%d",&x,&y,&l,&r);            int u=solo1(l);            int v=solo2(r);            if(u==-1||v==-1||x>y)            {                printf("0\n");            }            else            {                u++,v++;                printf("%d\n",query(u,v,1,n,root[x-1],root[y]));            }        }    }    return 0;}
0 0
原创粉丝点击