描述
数轴上有n个点,对于任一闭区间 [a, b],试计算落在其内的点数。
输入
第一行包括两个整数:点的总数n,查询的次数m。
第二行包含n个数,为各个点的坐标。
以下m行,各包含两个整数:查询区间的左、右边界a和b。
输出
对每次查询,输出落在闭区间[a, b]内点的个数。
样例
Input
5 2
1 3 7 9 11
4 6
7 12
Output
0
3
限制
0 ≤ n, m ≤ 5×105
对于每次查询的区间[a, b],都有a ≤ b
各点的坐标互异
各点的坐标、查询区间的边界a、b,均为不超过10^7的非负整数
时间:2 sec
内存:256 MB
题目不算难,思路也比较容易想到:先进行排序,然后进行二分查找。
由于左右边界的要求是不一样的,因此写了两个版本的查找。
另外需要注意的是在OJ系统中使用cin和cout会浪费大量的时间最终导致超时,因此最好使用scanf和printf,或者使用缓冲区。
下面贴出源代码,水平有限,有轻喷。
#include <iostream>
using namespace std;
void Merge(int* table, int low, int mid, int high)
{
int* A = table + low;
int lb = mid - low;
int* B = new int[lb];
for (int i = 0; i < lb; B[i] = A[i++]);
int lc = high - mid;
int* C = table + mid;
for (int i = 0, j = 0, k = 0; (j < lb) || (k < lc);)
{
if ((j < lb) && (lc <= k || (B[j] <= C[k])))
{
A[i++] = B[j++];
}
if ((k < lc) && (lb <= j || (C[k] < B[j])))
{
A[i++] = C[k++];
}
}
delete[] B;
}
void MergeSort(int* data, int low, int high)
{
if (high - low < 2)
{
return;
}
int mid = (low + high) / 2;
MergeSort(data, low, mid);
MergeSort(data, mid, high);
Merge(data, low, mid, high);
}
int upbinarysearch(int* A, int e, int low, int high)
{
while (low < high)
{
int mid = (low + high) / 2;
if (e < A[mid])
{
high = mid;
}
else if (e > A[mid])
{
low = mid + 1;
}
else
{
return mid;
}
}
if (e < A[low])
{
return low;
}
else
{
return low++;
}
}
int downbinarysearch(int* A, int e, int low, int high)
{
while (low < high)
{
int mid = (low + high) / 2;
if (e < A[mid])
{
high = mid;
}
else if (e > A[mid])
{
low = mid + 1;
}
else
{
return mid+1;
}
}
if (e > A[high])
{
return high;
}
else
{
return high++;
}
}
int main()
{
int n, times, a, b, p, q;
scanf("%d%d", &n, ×);
int* table = new int[n];
for (int i = 0; i < n; i++)
{
scanf("%d", &table[i]);
}
MergeSort(table, 0, n);
for (int i = 0; i < times; i++)
{
scanf("%d%d", &a, &b);
p = downbinarysearch(table, b, 0, n);
q = upbinarysearch(table, a, 0, n);
int delta = p - q;
printf("%d\n", delta);
}
}