范围查询(Range)

Descriptioin

Let S be a set of n integral points on the x-axis. For each given interval [a, b], you are asked to count the points lying inside.

Input

The first line contains two integers: n (size of S) and m (the number of queries).

The second line enumerates all the n points in S.

Each of the following m lines consists of two integers a and b and defines an query interval [a, b].

Output

The number of points in S lying inside each of the m query intervals.

Example

Input

5 2
1 3 7 9 11
4 6
7 12

Output

0
3

Restrictions

0 <= n, m <= 5 * 10^5

For each query interval [a, b], it is guaranteed that a <= b.

Points in S are distinct from each other.

Coordinates of each point as well as the query interval boundaries a and b are non-negative integers not greater than 10^7.

Time: 2 sec

Memory: 256 MB

描述

数轴上有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

思路

1.使用快速排序,先将所给数轴上的坐标进行排序

2.在数组中找lowerBound的所在数组中的下标位置:
             lowerBound存在数组中,返回当前下标i
             lowerBound不存在,则可找到该值在数组下标范围[i,i+1]中间,返回i+1

3.在数组中找upperBound的所在数组中的下标位置[lowerBound下标, n]:
             upperBound存在数组中,返回当前下标j
             upperBound不存在,则可找到该值在数组下标范围[j,j+1]中间,返回i

4.得到区间内数组个数:j - i + 1

#include <cstdio>

using namespace std;

int BinarySearch(int* NumGroup, int left, int right, int x, bool flag);
void qsort(int* NumGroup, int lo, int hi);
void swap(int* NumGroup, int i, int j);

int main()
{
#ifndef _OJ_
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif

	// 数组总数
	int n = 0;
	scanf("%d\n", &n);

	// 范围数
	int rangeNum = 0;
	scanf("%d\n", &rangeNum);

	// 数组元素填充
	int* NumGroup = new int[n + 2];
	NumGroup[0] = -1;
	NumGroup[n + 1] = 10e7 + 1;
	for (int i = 1; i < n + 1; ++i)
		scanf("%d\n", &NumGroup[i]);

	qsort(NumGroup, 1, n);
	n = n + 2;

	int** descriptioin = new int*[rangeNum];
	for (int i = 0; i < rangeNum; ++i)
	{
		descriptioin[i] = new int[2];
		scanf("%d\n", &descriptioin[i][0]);
		scanf("%d\n", &descriptioin[i][1]);
	}

	for (int i = 0; i < rangeNum; ++i)
	{
		int lowerBound = BinarySearch(NumGroup, 0, n - 1, descriptioin[i][0], false);
		int upperBound = BinarySearch(NumGroup, lowerBound, n - 1, descriptioin[i][1], true);
		printf("%d\n", upperBound - lowerBound + 1);
	}

#ifndef _OJ_
	fclose(stdin);
	fclose(stdout);
#endif
	return 0;
}

// int flag 上界true或下届false
int BinarySearch(int* NumGroup, int left, int right, int x, bool flag)
{
	int mid = (left + right + 1) / 2;
	if (NumGroup[mid] == x)
		return mid;

	if (NumGroup[mid - 1] < x && x < NumGroup[mid])
	{
		if (flag)
			return mid - 1;
		else 
			return mid;
	}

	if (x < NumGroup[mid])
		return BinarySearch(NumGroup, left, mid - 1, x, flag);
	else
		return BinarySearch(NumGroup, mid, right, x, flag);
}

void qsort(int* NumGroup, int lo, int hi)
{
	if (lo > hi)
		return;

	int base = NumGroup[lo];
	int i = lo;
	int j = hi;
	while (i != j)
	{
		while (NumGroup[j] >= base && i < j)
			j--;
		while (NumGroup[i] <= base && i < j)
			i++;


		swap(NumGroup, i, j);
	}

	swap(NumGroup, lo, i);
	qsort(NumGroup, lo, i - 1);
	qsort(NumGroup, i + 1, hi);
}

void swap(int* NumGroup, int i, int j)
{
	int temp = NumGroup[i];
	NumGroup[i] = NumGroup[j];
	NumGroup[j] = temp;
}

 

### SQL查询类型为range时索引失效的条件及原因 在SQL查询中,当查询类型为`range`时,索引可能因为多种因素导致失效。以下是一些常见的条件和原因: 1. **数据量问题** 当查询结果占总表数据的比例较高时,MySQL优化器可能会认为使用索引效率不如直接进行全表扫描,因此会放弃使用索引。这种情况通常发生在范围查询(如`WHERE column > value`)中,因为范围查询可能导致大量的行被扫描,而索引的效率优势在这种情况下会被削弱[^1]。 2. **范围查询中的非唯一索引字段** 在Oracle数据库中,如果使用了非唯一索引字段作为范围查询的条件,并且包含了小于条件(例如`WHERE column < value`),则可能导致索引失效。这是因为底层执行计划会将非唯一索引与`rowid`合为联合索引,从而导致范围无法有效使用索引。然而,大于或等于条件(例如`WHERE column >= value`)通常可以正常使用索引[^2]。 3. **OR条件中的非索引列** 如果在`WHERE`子句中使用了`OR`操作符,并且其中一个条件列是索引列,而另一个条件列不是索引列,则可能导致索引失效。例如: ```sql EXPLAIN SELECT create_time FROM user WHERE code = 1001 OR name = '派大星'; ``` 在此查询中,如果`code`字段有索引而`name`没有,则整个查询可能不会使用索引[^3]。 4. **函数或计算操作** 如果在索引列上执行任何计算或函数操作(例如`YEAR(birthdate)`),则会导致索引结构被破坏,使得数据库无法直接使用索引。例如: ```sql SELECT * FROM users WHERE YEAR(birthdate) = 1990; ``` 这种情况下,即使`birthdate`字段上有索引,也无法利用该索引来加速查询。 5. **最左前缀原则未遵循** 在使用联合索引时,如果没有按照索引创建时的顺序使用字段,或者中间缺少某些字段,则可能导致索引失效。例如: ```sql SELECT * FROM employees WHERE department = 'Sales' AND position = 'Manager'; ``` 如果联合索引是基于`(department, position, employee_id)`创建的,但查询中没有包含`employee_id`字段,则可能无法充分利用索引[^4]。 6. **覆盖索引未实现** 覆盖索引是指查询的所有列都在索引中存在,这样可以避免回表查询带来的额外开销。如果没有使用覆盖索引,则可能导致索引失效。例如: ```sql SELECT user_id, status FROM orders WHERE user_id = 12345 AND status = 'shipped'; ``` 如果`user_id`和`status`字段共同构成了一个复合索引,则上述查询可以利用该索引来加速查询过程。但如果查询中包含了其他不在索引中的字段,则需要回表查询,这可能导致性能下降。 7. **IS NULL 或 IS NOT NULL 条件** 在索引字段上使用`IS NULL`或`IS NOT NULL`条件时,也可能导致索引失效。这是因为这些条件通常涉及较多的行数,优化器可能会选择不使用索引。 ### 示例代码 下面是一个示例,展示了如何正确使用索引来优化查询: ```sql -- 正确使用覆盖索引的例子 SELECT user_id, status FROM orders WHERE user_id = 12345 AND status = 'shipped'; ``` 而下面的例子则展示了错误地使用了函数导致索引失效的情况: ```sql -- 错误使用函数导致索引失效 SELECT * FROM users WHERE YEAR(birthdate) = 1990; ``` 最后,考虑以下查询,它违反了最左前缀原则: ```sql -- 违反最左前缀原则 SELECT * FROM employees WHERE department = 'Sales' AND position = 'Manager'; ``` 为了修复这个问题,应该确保查询条件中的字段按照索引创建时的顺序出现,并且连续。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值