版权声明:本文为博主原创文章,转载请标明出处 https://blog.csdn.net/MOMING_V/article/details/82948075
10月5日备战Noip2018模拟赛7(B组)
T2 Pearl 数数
题目描述
给定n个整数,求值在某个范围内的数的个数。
输入格式
第一行为正整数n。
第二行有n个整数(0<=数值<=231-1。)
第三行为正整数m,表示总询问次数。
以下m行,每行两个整数Ai,Bi(1<=Ai,Bi <= 2^31 - 1),表示询问值在[Ai,Bi]内的数个数(如果Ai>Bi则交换Ai,Bi)。
输出格式
输出m行,对于每次询问输出一行,表示值在[Ai,Bi]范围内的数的个数。
输入样例
7
8 2 3 5 6 7 7
6
1 5
8 6
1 10
5 5
4 4
7 8
输出样例
3
4
7
1
0
3
数据范围
对于25%的数据,有m,n<=1000。
对于100%的数据,有m,n<=100000
思路
sort + Binary searh
不过要注意有特判
二分后 l不一定小于r
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 100005;
int a[N];
int LowerBound (int left, int right, int x) //寻找第一个大于等于x的数
{
int mid;
while (left < right){
mid = (right - left) / 2 + left;
if (a[mid] >= x) right = mid;
else left = mid + 1;
}
return left;
}
int UpperBound (int left, int right, int x) //寻找第一个大于x的数
{
int mid;
while (left < right){
mid = (right - left) / 2 + left;
if (a[mid] > x) right = mid;
else left = mid + 1;
}
return left;
}
int main ()
{
//freopen ("pearl.in", "r", stdin);
//freopen ("pearl.out", "w", stdout);
int n, m, l, r, ans;
scanf ("%d", & n);
for (int i = 1; i <= n; i ++){
scanf ("%d", & a[i]);
}
sort (a + 1, a + 1 + n); //升序排列,方便二分
scanf ("%d", & m);
for (int i = 1; i <= m; i ++){
scanf ("%d %d", & l, & r);
if (l > r) swap (l, r);
if (r < a[1] || l > a[n]) ans = 0; //所选的值不在给出的n个数内
else {
if (l <= a[1]) l = 1;
else l = LowerBound (1, n, l);
if (r >= a[n]) r = n + 1;
else r = UpperBound (1, n, r);
r -= 1;
if (l > r) ans = 0; //特判l会不会大于r
else ans = r - l + 1;
}
printf ("%d\n", ans);
}
//fclose (stdin);
//fclose (stdout);
return 0;
}