【C++实现】归并排序 二分法查找

范围查询(Range)


描述

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

输入

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

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

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

输出

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

样例

  输入

5 3
1 3 7 9 11
4 6
7 12
0 8

  输出

0
3
3

数据范围

  0 ≤ n, m ≤ 500,000

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

  各点的坐标互异

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

资源限制

  时间:2 sec

  内存:256 MB

 

#define _CRT_SECURE_NO_WARNINGS

#include<iostream>
using namespace std;
int *v; // 存放数轴

void merge(size_t lo, size_t mi, size_t hi)
{
	int lb = mi - lo;
	int lc = hi - mi;

	int *A = v + lo;
	int *B = new int[lb];
	int *C = v + mi;

	for (size_t i = 0; i < lb; i++)
	{
		B[i] = A[i];
	}
	for (size_t i = 0, j = 0, k = 0; (j < lb) || (k < lc);)
	{
		if (j < lb && (k >= lc || B[j] <= C[k])) A[i++] = B[j++];
		if (k < lc && (j >= lb || B[j] > C[k])) A[i++] = C[k++];
	}
	delete[] B;
}

void mergeSort(size_t lo, size_t hi)
{
	if (hi - lo < 2) return;//只有一个元素,返回
	size_t mi = (hi + lo) / 2;
	mergeSort(lo, mi);//分别排序
	mergeSort(mi, hi);
	merge(lo, mi, hi);//归并
}
int binaryFind(int e, int lo, int hi)
{
	while (lo < hi)
	{
		int mi = (lo + hi) / 2;
		(e < v[mi]) ? hi = mi : lo = mi + 1;
	}
	return --lo;
}
int main()
{
	setvbuf(stdin, new char[1 << 20], _IOFBF, 1 << 20); // 设置I/O缓冲区,加速读写
	//setvbuf(stdout, new char[1 << 20], _IOFBF, 1 << 20);
	int n, m;
	scanf("%d%d", &n, &m);//点数,查询的次数
	v = new int[n]; // 存放数轴
	for (int i = 0; i < n; i++)
		scanf("%d", &v[i]); // 请使用scanf读入,cin读入长的行较慢
	mergeSort(0, n);
	for (size_t i = 0; i < n; i++)
	{
		cout << v[i] << " ";
	}
	cout << endl;
	for (int i = 0; i < m; i++) {
		int a, b;
		scanf("%d%d", &a, &b);
		int cnt = 0;
		int left = binaryFind(a, 0, n);
		if (left < 0) left = 0;
		int right = binaryFind(b, left, n);


		if (right < 0) cnt = 0;
		else if (v[left]>=a) cnt = right - left+1;
		else cnt = right - left;
		printf("%d\n", cnt);
	}

	system("pause");
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值