数据结构(Tsinghua--范围查询(Range))

博客探讨了在数轴上处理范围查询的问题,描述了如何通过排序和二分查找来计算给定区间内的点数。给出了样例输入输出及性能限制,并指出原始方法与优化方法之间的效率差异。

描述

数轴上有n个点,对于任一闭区间 [a, b],试计算落在其内的点数。

输入

第一行包括两个整数:点的总数n,查询的次数m。

第二行包含n个数,为各个点的坐标。

以下m行,各包含两个整数:查询区间的左、右边界a和b。

输出

对每次查询,输出落在闭区间[a, b]内点的个数。

样例

Input

5 2
1 3 7 9 11
4 6
7 12

Output

0
3

限制

0 ≤ n, m ≤ 5×105

对于每次查询的区间[a, b],都有a ≤ b

各点的坐标互异

各点的坐标、查询区间的边界a、b,均为不超过10^7的非负整数

时间:2 sec

内存:256 MB

解题思路:

很容易想到对所有点进行排序,然后通过二分查找,找到对应范围的下标,进而相减即为范围内点数。


#include <cstdio>  
#include <cstdlib>

int room[500010];

//不存在则返回小于该值的最后一个元素的pos(包含哨兵[lo-1])
int mybinsearch(int v[], int const& e, int lo, int hi) {
	while (lo < hi) {
		int mi = (lo + hi) >> 1;
		(e < v[mi]) ? hi = mi : lo = mi + 1;
	}
	return --lo;//返回所搜索值的前一个pos
}

int cmp(const void *a, const void *b)
{
	return *(int*)a - *(int*)b;
}
int mymax(int a, int b)
{
	return (a > b ? a : b);
}
int main()
{
	int N, M;
	scanf("%d %d", &N, &M);

	for (int i = 0; i < N; ++i)
	{
		scanf("%d", &room[i]);
	}
	qsort(room,N, sizeof(int), cmp);

	int start, end;

	for (auto i = 0; i < M; ++i)
	{
		scanf("%d %d", &start, &end);
		int s = mybinsearch(room, start, 0, N);
		int e = mybinsearch(room, end, mymax(s,0), N);
		if (s >= 0 && room[s] == start)
			s--;
		printf("%d\n", e - s);
	}

	return 0;
}

代码对应结果如下:

Case No.ResultTime(ms)Memory(KB)
1Accepted06456
2Accepted06456
3Accepted06456
4Accepted06456
5Accepted06456
6Accepted06456
7Accepted06456
8Accepted06456
9Accepted06456
10Accepted06456
11Accepted06456
12Accepted366692
13Accepted486772
14Accepted206772
15Accepted606848
16Accepted727044
17Accepted1167160
18Accepted1327240
19Accepted2088412
20Accepted3608412

这里列出当前Top10的结果

EmailScoreWorst CaseTime(ms)Memory(KB)
suzq**100.020

68 

22580 

zhong3**100.020

72 

44484 

hhyl**100.020

108 

66428 

[Anonymous]100.020

116 

53076 

hongyuan_de**100.020

124 

30984 

wunschunre**100.020

132 

53332 

3830670**100.020

136 

53048 

li-ch**100.020

140 

84308 

4505632**100.020

144 

66608 

gwy**100.020

148 

52524 

可以看到相差较大,那么进行优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值