范围查询(Range)
描述
数轴上有n个点,对于任一闭区间 [a, b],试计算落在其内的点数。
输入
第一行包括两个整数:点的总数n,查询的次数m。
第二行包含n个数,为各个点的坐标。
以下m行,各包含两个整数:查询区间的左、右边界a和b。
输出
对每次查询,输出落在闭区间[a, b]内点的个数。
样例
输入
5 3
1 3 7 9 11
4 6
7 12
0 8
输出
0
3
3
数据范围
0 ≤ n, m ≤ 500,000
对于每次查询的区间[a, b],都有a ≤ b
各点的坐标互异
各点的坐标、查询区间的边界a、b,均为不超过10^9的非负整数
资源限制
时间:2 sec
内存:256 MB
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
int *v; // 存放数轴
void merge(size_t lo, size_t mi, size_t hi)
{
int lb = mi - lo;
int lc = hi - mi;
int *A = v + lo;
int *B = new int[lb];
int *C = v + mi;
for (size_t i = 0; i < lb; i++)
{
B[i] = A[i];
}
for (size_t i = 0, j = 0, k = 0; (j < lb) || (k < lc);)
{
if (j < lb && (k >= lc || B[j] <= C[k])) A[i++] = B[j++];
if (k < lc && (j >= lb || B[j] > C[k])) A[i++] = C[k++];
}
delete[] B;
}
void mergeSort(size_t lo, size_t hi)
{
if (hi - lo < 2) return;//只有一个元素,返回
size_t mi = (hi + lo) / 2;
mergeSort(lo, mi);//分别排序
mergeSort(mi, hi);
merge(lo, mi, hi);//归并
}
int binaryFind(int e, int lo, int hi)
{
while (lo < hi)
{
int mi = (lo + hi) / 2;
(e < v[mi]) ? hi = mi : lo = mi + 1;
}
return --lo;
}
int main()
{
setvbuf(stdin, new char[1 << 20], _IOFBF, 1 << 20); // 设置I/O缓冲区,加速读写
//setvbuf(stdout, new char[1 << 20], _IOFBF, 1 << 20);
int n, m;
scanf("%d%d", &n, &m);//点数,查询的次数
v = new int[n]; // 存放数轴
for (int i = 0; i < n; i++)
scanf("%d", &v[i]); // 请使用scanf读入,cin读入长的行较慢
mergeSort(0, n);
for (size_t i = 0; i < n; i++)
{
cout << v[i] << " ";
}
cout << endl;
for (int i = 0; i < m; i++) {
int a, b;
scanf("%d%d", &a, &b);
int cnt = 0;
int left = binaryFind(a, 0, n);
if (left < 0) left = 0;
int right = binaryFind(b, left, n);
if (right < 0) cnt = 0;
else if (v[left]>=a) cnt = right - left+1;
else cnt = right - left;
printf("%d\n", cnt);
}
system("pause");
return 0;
}