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

解法一:

  1. 原理与要点: 因为坐标的范围比较小,只有1e7,且均为非负数,就很容易想到用前缀和来解决这个问题。

求前缀和((a_i = sum_{j=0}^{i}b_j)(b_j)存储坐标为j的点的个数,(a_i)存储区间[0,i]内点的个数),对每次询问的(l,r)输出 $ a_r-a_{l-1}$

  1. 遇到的问题:
  2. 时间和空间复杂度:求前缀和时间复杂度(O(1e7)),每次查询复杂度(O(1))。理论复杂度比排序+二分的解法更优。空间复杂度(O(1e7))
  3. 特别或创新: 对于这道题的数据量来说,前缀和更快,编程更简单。
#include "iostream"
#include "cstdio"

using namespace std;
const int maxn = 1e7+ 100;
int a[maxn];

int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    int x;
    for (int i = 0; i < n; i++) {
        scanf("%d", &x);
        a[x]++;
    }
    for (int i = 1; i < maxn - 1; i++) {
        a[i] += a[i - 1];
    }
    int l, r;
    while (m--) {
        scanf("%d %d", &l, &r);
        if (l != 0)
            printf("%d
", a[r] - a[l - 1]);
        else
            printf("%d
", a[r]);
    }
    return 0;
}

解法二:

  1. 原理与要点:将所有的点存到一个数组里然后排序,每次询问时二分查找到左端点和右端点,相减得到查询结果
  2. 遇到的问题:
  3. 时间和空间复杂度:时间复杂度(O(nlogn)),空间复杂度(O(n))
  4. 特别或创新:
#include "cstdio"
#include "stdlib.h"
#include "iostream"

using namespace std;
const int maxn = 5e5 + 100;
const int inf = 0x3f3f3f3f;
const int SZ = 1 << 20;  //快速io
struct fastio {
    char inbuf[SZ];
    char outbuf[SZ];

    fastio() {
        setvbuf(stdin, inbuf, _IOFBF, SZ);
        setvbuf(stdout, outbuf, _IOFBF, SZ);
    }
} io;

int cmp(const void *a, const void *b) {
    return *(int *) a - *(int *) b;
}

int a[maxn];

int main() {
    int n, q;
    scanf("%d %d", &n, &q);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    a[0] = -inf;
    a[n + 1] = inf;
    qsort(a, n + 1, sizeof(a[0]), cmp);
    int x, y;
    int from, to;
    int l, r, mid;
    while (q--) {
        scanf("%d %d", &x, &y);
        l = 0, r = n + 1;
        while (l < r) {
            mid = (l + r + 1) >> 1;
            if (a[mid] >= x) r = mid - 1;
            else l = mid;
        }
        from = l;
        l = 0, r = n + 1;
        while (l < r) {
            mid = (l + r) >> 1;
            if (a[mid] <= y) l = mid + 1;
            else r = mid;
        }
        to = l;
        printf("%d
", to - from - 1);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/albert-biu/p/11542093.html