题目大意:
给定n个点(1 ≤ n ≤ 10^5),每个点都有一个整数值,范围是[0, 10^8],并且已经升序排列好了(每个点的值互不相同),现在给定q个段[a, b],其中a、b∈[0, 10^8],计算序列中每个给定段中点的个数,即p∈序列,且a ≤ p ≤ b的p的个数。
现有多个测例(测例数会给出),每个测例中都给出n和q,以及n个元素的大小(升序排列输入的)以及q个段的左端值和右端值a和b,对于每个测例的每个段都给出位于段中的元素的个数。
C语言实现lower_bound和upper_bound:
注释代码:
/*
* Problem ID : LOJ 1088 Points in Segments
* Author : Lirx.t.Una
* Language : C++
* CPU : 0.340
* Memory : 1476
*/
#include <stdio.h>
//点集的最大长度
#define MAXN 100000
int a[MAXN];
int
xbsrch( int lft, int rht, int x ) {//binary search in x
//搜出大于等于x的第一个元素,即lower_bound
int mid;
while ( lft < rht ) {
mid = ( lft + rht ) >> 1;
if ( a[mid] >= x )//一旦大于等于x就将区间置为左部
rht = mid;//此步保证结果位置一定最左
else//小于就mid左移
//此步保证了结果位置的元素一定大于等于x
lft = mid + 1;
}
return lft;
}
int
ybsrch( int lft, int rht, int y ) {//binary search in y
//搜出大于y的第一个元素,即upper_bound
int mid;
while ( lft < rht ) {
mid = ( lft + rht ) >> 1;
if ( a[mid] > y )//一旦大于y就将区间置为右部
rht = mid;//此步保证结果位置一定最右
else//小于等于就mid右移
//此步保证了结果一定大于y
lft = mid + 1;
}
return lft;
}
int
main() {
int nscn, iscn;
int n, k;//n个点k个段
int x, y;//搜查的左右端点
int p1, p2;//搜查结果的左右端点的数组下标
int i;
scanf("%d", &nscn);
iscn = 0;
while ( nscn-- ) {
scanf("%d%d", &n, &k);
for ( i = 0; i < n; i++ )
scanf("%d", a + i);
printf("Case %d:\n", ++iscn);
while ( k-- ) {
scanf("%d%d", &x, &y);
if ( a[n - 1] < x || a[0] > y ) {
//如果搜查区间和点序列不重合
//则无任何元素
puts("0");
continue;
}
//特殊情况(y的srch不能正确处理这种特殊情况)
if ( x <= a[0] )//当左搜查元素小于等于序列最左端值
p1 = 0;//则左坐标就直接等于0(0号元素就是大于等于x的第一个元素了)
else
p1 = xbsrch( 0, n - 1, x );
if ( y >= a[n - 1] )//对于这种情况若使用ysrch,则其返回的就是
//序列的最后一个元素,而不是最后一个元素的后一个位置
p2 = n;
else
p2 = ybsrch( p1, n - 1, y );//利用p1作为左端点,可以剪短搜索范围以节省时间
printf("%d\n", p2 - p1);
}
}
return 0;
}
无注释代码:
#include <stdio.h>
#define MAXN 100000
int a[MAXN];
int
xbsrch( int lft, int rht, int x ) {
int mid;
while ( lft < rht ) {
mid = ( lft + rht ) >> 1;
if ( a[mid] >= x )
rht = mid;
else
lft = mid + 1;
}
return lft;
}
int
ybsrch( int lft, int rht, int y ) {
int mid;
while ( lft < rht ) {
mid = ( lft + rht ) >> 1;
if ( a[mid] > y )
rht = mid;
else
lft = mid + 1;
}
return lft;
}
int
main() {
int nscn, iscn;
int n, k;
int x, y;
int p1, p2;
int i;
scanf("%d", &nscn);
iscn = 0;
while ( nscn-- ) {
scanf("%d%d", &n, &k);
for ( i = 0; i < n; i++ )
scanf("%d", a + i);
printf("Case %d:\n", ++iscn);
while ( k-- ) {
scanf("%d%d", &x, &y);
if ( a[n - 1] < x || a[0] > y ) {
puts("0");
continue;
}
if ( x <= a[0] )
p1 = 0;
else
p1 = xbsrch( 0, n - 1, x );
if ( y >= a[n - 1] )
p2 = n;
else
p2 = ybsrch( p1, n - 1, y );
printf("%d\n", p2 - p1);
}
}
return 0;
}
使用lower_bound和upper_bound二分搜索模板函数:
/*
* Problem ID : LOJ 1088 Points in Segments
* Author : Lirx.t.Una
* Language : C++
* CPU : 0.364
* Memory : 2076
*/
#include <algorithm>
#include <iostream>
#include <cstdio>
#define MAXN 100001
using namespace std;
int a[MAXN];
int
main() {
int nscn, iscn;
int n, k;
int x, y;
int p1, p2;
int i;
scanf("%d", &nscn);
iscn = 0;
while ( nscn-- ) {
scanf("%d%d", &n, &k);
for ( i = 0; i < n; i++ )
scanf("%d", a + i);
printf("Case %d:\n", ++iscn);
while ( k-- ) {
scanf("%d%d", &x, &y);
p1 = lower_bound(a, a + n, x) - a;
p2 = upper_bound(a + p1, a + n, y) - a;
printf("%d\n", p2 - p1);
}
}
return 0;
}
单词解释:
dimensional:adj, 维度的,空间上的
n dimensional:adj, n维的