范围查询(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
解法一:
- 原理与要点: 因为坐标的范围比较小,只有1e7,且均为非负数,就很容易想到用前缀和来解决这个问题。
求前缀和((a_i = sum_{j=0}^{i}b_j) ,(b_j)存储坐标为j的点的个数,(a_i)存储区间[0,i]内点的个数),对每次询问的(l,r)输出 $ a_r-a_{l-1}$
- 遇到的问题: 无
- 时间和空间复杂度:求前缀和时间复杂度(O(1e7)),每次查询复杂度(O(1))。理论复杂度比排序+二分的解法更优。空间复杂度(O(1e7))
- 特别或创新: 对于这道题的数据量来说,前缀和更快,编程更简单。
#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;
}
解法二:
- 原理与要点:将所有的点存到一个数组里然后排序,每次询问时二分查找到左端点和右端点,相减得到查询结果
- 遇到的问题: 无
- 时间和空间复杂度:时间复杂度(O(nlogn)),空间复杂度(O(n))
- 特别或创新: 无
#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;
}