学堂在线《数据结构》编程题

范围查询(Range)


Descriptioin

Let S be a set of n integral points on the x-axis. For each given interval [a, b], you are asked to count the points lying inside.

Input

The first line contains two integers: n (size of S) and m (the number of queries).

The second line enumerates all the n points in S.

Each of the following m lines consists of two integers a and b and defines an query interval [a, b].

Output

The number of points in S lying inside each of the m query intervals.

Example

Input

5 2
1 3 7 9 11
4 6
7 12

Output

0
3

Restrictions

0 <= n, m <= 5 * 10^5

For each query interval [a, b], it is guaranteed that a <= b.

Points in S are distinct from each other.

Coordinates of each point as well as the query interval boundaries a and b are non-negative integers not greater than 10^7.

Time: 2 sec

Memory: 256 MB

描述

数轴上有n个点,对于任一闭区间 [a, b],试计算落在其内的点数。

输入

第一行包括两个整数:点的总数n,查询的次数m。

第二行包含n个数,为各个点的坐标。

以下m行,各包含两个整数:查询区间的左、右边界a和b。

输出

对每次查询,输出落在闭区间[a, b]内点的个数。

样例

见英文题面

限制

0 ≤ n, m ≤ 5×105

对于每次查询的区间[a, b],都有a ≤ b

各点的坐标互异

各点的坐标、查询区间的边界a、b,均为不超过10^7的非负整数

时间:2 sec

内存:256 MB

#include <stdio.h>
using namespace std;
int points[500010];
int m,n;
void merge(int low,int mi,int high)
{
    int l=high-low;
    int*temp=new int[l];
    for(int i=0,j=low,k=mi;j<mi||k<high;)
    {
        if(j<mi&&(k>=high||points[j]<=points[k])) temp[i++]=points[j++];
        if(k<high&&(j>=mi||points[j]>points[k])) temp[i++]=points[k++];
    }
    for(int i=0;i<l;i++)
    {
        points[low+i]=temp[i];    
    } 
    delete [] temp; 
}
void mergesort(int low,int high)
{
    if(high-low<2) return;
    int mi=(low+high)>>1;
    mergesort(low,mi);
    mergesort(mi,high);
    merge(low,mi,high);
}

int find(int e,int low,int high)
{
    while(high>low)
    {
        int mi=(low+high)/2;
        (e<points[mi]) ? high=mi:low=mi+1;
    }
    return --low;//若查找不到,需要注意:若小于最小数,返回的是-1;若大于最大的数,则返回的是最大的 
}
int main()
{
    scanf("%d %d",&n,&m);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&points[i]);
    } 
    //sort
    mergesort(0,n);
    while(m--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        int t=find(a,0,n);
        if(t!=-1) (a==points[t]) ? a=t:a=t+1;
        else a=0;
        b=find(b,0,n);
        printf("%d\n",b-a+1);
    }
    return 0;
}

好久没弄代码,开始继续修炼了,学完这门课,大概就可以准备考PAT甲级了。

由于清华的这个OJ把很多东西都禁用了,一向偷懒的我只能自己慢慢写了,一些基础的,比如这一题的二分法,归并排序之类的,可参看教材上的例子,还有要注意特殊情况,我又一次忽略了。

猜你喜欢

转载自www.cnblogs.com/fremontxutheultimate/p/10533136.html