范围查询(Range)

范围查询(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

这道题是邓峻辉 数据结构课程中,第一道编程题
题目的大意是输出原有序列S中,在指定范围[a, b]中数的个数;

解法:
1. 先将原有的序列S进行排序;
2. 使用两个版本的二分查找对a和b进行查找;
3. 输出两个查找结果的差;

#include <cstdio>
#include <cstdlib>

const int SZ = 1 << 20;
struct fastio { /*大io,加速输入和输出*/
    char inbuf[SZ];
    char outbuf[SZ];
    fastio() {
        setvbuf(stdin, inbuf, _IOFBF, SZ);
        setvbuf(stdout, outbuf, _IOFBF, SZ);
    }
}io;

int tot;    /*输入序列中元素的总个数*/
int points[500005];
/*查找最后一次出现e的位置, 若原序列中没有元素e,则返回在原序列中插入e后 e所在的位置*/
inline int searchBack(const int e)
{
    int lo = 0, hi = tot;
    int mi = 0;
    while (lo < hi) {
        mi = (lo + hi) >> 1;
        e < points[mi] ? hi = mi : lo = mi + 1;
    }
    return lo;
}
/*查找第一次出现e的位置,若原序列中没有元素e,则返回在原序列中插入e后 e所在的位置*/
inline int searchFront(const int e)
{
    int lo = 0, hi = tot, mi = 0;
    while (lo < hi) {
        mi = (lo + hi) >> 1;
        e > points[mi] ? lo = mi + 1 : hi = mi;
    }
    return lo;
}
inline int compare(const void *a, const void *b) { 
    if (*(int *)a != *(int *)b)
        return (*(int *)a > *(int *)b);
    else return 0; 
}
int main(void)
{
    int m, n;
    scanf("%d%d", &n, &m);
    tot = n;

    for (int i = 0; i < n; i++) {
        scanf("%d", &points[i]);
    }
    qsort(points, tot, sizeof(int), &compare);  /*原序列可能是无序的,使用快速排序算法排序*/
    int start, end;
    for (int i = 0; i < m; i++) {
        scanf("%d%d", &start, &end);
        printf("%d\n", searchBack(end) - searchFront(start));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值