1
#include <stdio.h>
#include <stdlib.h>
//比较函数
int compare(const void *a, const void *b)
{
return (*(int *)a - *(int *)b);
}//a > b整数 0:a==b
int main()
{
int n, q;
scanf("%d %d", &n, &q);
int arr[n];
for (int i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
qsort(arr, n, sizeof(int), compare);//arr按升序排序
while (q--)
{
int l, r;
scanf("%d %d", &l, &r);
int *left = (int *)bsearch(&l, arr, n, sizeof(int), compare);//bsearch:标准库中的二分查找函数
//&l:要找的值的地址
if (left == NULL)
{
// 如果没有找到 >= l 的元素,用 lower_bound找第一个比l大的位置
int low = 0, high = n;// low:查找下界
while (low < high)
{
int mid = (low + high) / 2;
if (arr[mid] < l)
low = mid + 1;
else
high = mid;//中间元素大于等于l调整上界
}
left = &arr[low];
}
else
{
// 找到第一个 >= l 的元素的最左位置
while (left > arr && *(left - 1) == l) //防止指针越界(不超出数组首地址)
left--; //检查前一个元素是否也等于l
}
// 第一个 > r 的元素位置
int *right = (int *)bsearch(&r, arr, n, sizeof(int), compare);
if (right == NULL)
{
// 如果没有找到 > r 的元素,用 upper_bound
int low = 0, high = n;
while (low < high)
{
int mid = (low + high) / 2;
if (arr[mid] <= r)
low = mid + 1;
else
high = mid;
}
right = &arr[low];
}
else
{
// 找到第一个 > r 的元素的最左位置
while (right < arr + n && *right == r)
right++;
}
printf("%ld\n", right - left);//指针算术运算
}
◮:排序 + 二分查。先数组排序,然后每个区间 [l, r],用二分找到大于等于 l 的第一个元素位置和小于等于 r 的最后一个元素位置,两者的差就是区间内元素的个数
43line:当bsearch找到匹配元素时,可能不是第一个出现的位置∵数组有重复元素,这个循环向左移动指针,直到找到第一个等于l的元素最左位置)
◮:
浙公网安备 33010602011771号