light oj 1088 (二分)

Description

Given n points (1 dimensional) and q segments, you have to find the number of points that lie in each of the segments. A point pi will lie in a segment A B if A ≤ pi ≤ B.

For example if the points are 1, 4, 6, 8, 10. And the segment is 0 to 5. Then there are 2 points that lie in the segment.


Input

Input starts with an integer T (≤ 5), denoting the number of test cases.

Each case starts with a line containing two integers n (1 ≤ n ≤ 105) and q (1 ≤ q ≤ 50000). The next line contains n space separated integers denoting the points in ascending order. All the integers are distinct and each of them range in [0, 108].

Each of the next q lines contains two integers Ak Bk (0 ≤ Ak ≤ Bk ≤ 108) denoting a segment.

Output

For each case, print the case number in a single line. Then for each segment, print the number of points that lie in that segment.

Sample Input

1

5 3

1 4 6 8 10

0 5

6 10

7 100000

Sample Output

Case 1:

2

3

2

题意为给出一串数,再给出两个数 ,查找这串数中有多少个数字在这两个数之间。

开始想到了线段树,不会写啊~~~。看到大家纷纷ac想一定有其他办法,经过巨巨的提醒因为于数据量很大,所以用二分枚举区间的起始点和终点在数列中的位置。
这道题的两个函数的返回值很值得推敲,开始还云里雾里的我,推了几次就明白了这个逻辑。(由于输入输出量很大,还应该用scanf printf,用了cin cout会超时的)。
 
 
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int a[maxn];
int n,m;

int _lower(int l){
	int L,R,mid;
	L = 1; R = n; mid = 0;
	while(L<=R){
		mid=(L+R)>>1;
		if(a[mid]<l) L=mid+1;
		if(a[mid]>l) R=mid-1;
		if(a[mid]==l) return mid;
	}
	return L;
}

int _higher(int r){
	int L,R,mid;
	L = 1; R = n; mid = 0;
	while(L<=R){
		mid=(L+R)>>1;
		if(a[mid]>r) R=mid-1;
		if(a[mid]<r) L=mid+1;
		if(a[mid]==r) return mid;
	}
	return R;
}

int main(){
	int T,l,r,t,ll,rr;
	scanf("%d",&T);
	t = 1;ll = rr = 0;
	while(T--){
		scanf("%d %d",&n,&m);
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
		}
		printf("Case %d:
",t++);
		for(int i=1;i<=m;i++){
			scanf("%d %d",&l,&r);
			ll=_lower(l);
			rr=_higher(r);
			printf("%d
",rr-ll+1);
		}
	}
	return 0;
}
 
 
原文地址:https://www.cnblogs.com/gjy963478650/p/7301797.html