10月5日备战Noip2018模拟赛7(B组)
T2珍珠数
题目描述
给定Ñ个整数,求值在某个范围内的数的个数。
输入格式
第一行为正整数ñ。
第二行有Ñ个整数(0 <=数值<= 231-1)。
第三行为正整数米,表示总询问次数。
以下m行,每行两个整数Ai,Bi(1 <= Ai,Bi <= 2 ^ 31 - 1),表示询问值在[Ai,Bi]内的数个数(如果Ai> Bi则交换Ai ,双)。
输出格式
输出米行,对于每次询问输出一行,表示值在[艾,铋]范围内的数的个数。
输入样例
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 <= 10万
思路
排序+二进制搜索
不过要注意有特判
二分后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;
}