范围查询(Range)

<pre name="code" class="plain">描述
数轴上有n个点,对于任一闭区间 [a, b],试计算落在其内的点数。

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

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

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

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


限制
0 ≤ n, m ≤ 5×105

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

各点的坐标互异

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

时间:2 sec

内存:256 MB

Example
Input

5 2
1 3 7 9 11
4 6
7 12
Output

0
3

搞了好久,最后终于用快排加二分查询做出来了,刚开始怎么弄都超时。。。
最终的思路其实蛮简单的,就是将各个点存在一个数组里面,然后用快排排好,
之后输入要查询的左右区间的数,左区间的数进行查询后,返回一个下标,右区间的数进行查询后也返回一个数组下标,
然后下标相减即可,不过相减的时候也要分情况来弄
#include <stdio.h>
#include <stdlib.h>
#define N 500002

int range[N];

void quickSort(int lo, int high)
{
	int lo_t = lo, high_t = high;
	int temp = range[lo];
	if (lo > high)
	{
		return;
	}
	while (lo_t != high_t)
	{
		while (range[high_t] >= temp && lo_t < high_t)
		{
			high_t--;
		}
		while (range[lo_t] <= temp && lo_t < high_t)
		{
			lo_t++;
		}

		if (lo_t < high_t)
		{
			int temp = range[lo_t];
			range[lo_t] = range[high_t];
			range[high_t] = temp;
		}
	}
	range[lo] = range[lo_t];
	range[lo_t] = temp;

	quickSort(lo, lo_t - 1);
	quickSort(lo_t + 1, high);
	return;
}

int flag = 0;
int myBinary(int num, int low, int high)
{
	int middle;
	while (low <= high)
	{
		middle = (low + high) / 2;
		if (num < range[middle])
		{
			high = middle - 1;
		}
		else if (num > range[middle])
		{
			low = middle + 1;
		}
		else
		{
			flag = 1;
			return middle;
		}
	}
	return (low + high) / 2;
}
int main()
{
	int num, test, i;
	scanf("%d %d", &num, &test);
	for (i = 1; i <= num; i++)
	{
	    scanf("%d", range + i);
	}
	quickSort(1, num);

	while (test--)
	{
		int x, y, a, b, flag_a = 0, flag_b = 0;
		scanf("%d %d", &x, &y);//如果对x和y之间的数做一个循环,依次进行查询然后记录是否在点上,这样时间也会超,原来就是这么干的

		if (x != 0)//左区间不为0的情况
		{
			a = myBinary(x, 1, num);
			flag_a = flag;
		}
		else
		{
			a = 0;左区间为0的时候
			flag_a = flag;
		}

		flag = 0;

		if (y <= range[num])//右区间在数组范围内的情况
		{
			b = myBinary(y, 1, num);
			flag_b = flag;
		}
		else     //右区间不在数组范围内
		{
			b = num;
			flag_b = 1;
		}

		if ((flag_a && flag_b) || (flag_a && !flag_b))//左右区间刚好都在点上以及左区间在点上右区间不在点上的情况
		{
		    printf("%d\n", b - a + 1);
		}
		else if ((!flag_a && flag_b) || (!flag_a && !flag_b))//左区间不在点上右区间在点上以及左右区间都不在点上的情况
		{
			printf("%d\n", b - a);
		}
		flag = 0;
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值