前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ACM刷题之路(十八)二分 2019暑期集训 POJ 3579 Median

ACM刷题之路(十八)二分 2019暑期集训 POJ 3579 Median

作者头像
Designer 小郑
发布2023-08-01 08:12:07
1150
发布2023-08-01 08:12:07
举报
文章被收录于专栏:跟着小郑学JAVA跟着小郑学JAVA

题目链接:传送门

Description

Given N numbers, X1, X2, ... , XN, let us calculate the difference of every pair of numbers: ∣Xi - Xj∣ (1 ≤ i j N). We can get C(N,2) differences through this work, and now your task is to find the median of the differences as quickly as you can!

Note in this problem, the median is defined as the (m/2)-th  smallest number if m,the amount of the differences, is even. For example, you have to find the third smallest one in the case of m = 6.

Input

The input consists of several test cases. In each test case, N will be given in the first line. Then N numbers are given, representing X1, X2, ... , XN, ( Xi ≤ 1,000,000,000  3 ≤ N ≤ 1,00,000 )

Output

For each test case, output the median in a separate line.

Sample Input

代码语言:javascript
复制
4
1 3 2 4
3
1 10 2

Sample Output

代码语言:javascript
复制
1
8

题意:每一组数据给一个n,后面给n个数,求这些数之间的差绝对值的中位数,比如例子1 3 2 4 ,差为1,1,1,2,2,3,如果个数为偶数则取中间前面,奇数取中间的数。

分析:

要求差的中位数,最暴力的就是把所有的差都算出来,再sort排序,然后取中间的数输出,当然肯定超时。

我的做法是用两个二分,第一个二分中位数的值,第二个二分试探这个值的可行性

比如例子:

4

1 3 2 4

先对它排序  放入vector  然后是1 2 3 4

那么它一定有6个差  计算方法为1 + 2 + 3个差   即(1+n-1)*n/2 == (n-1)*n/2;

差的最小值假设是0,就是二分的起点s = 0 ;差一定大于0

最大值假设是a[n-1]-a[0]+1,也就是二分的终点e = 4;差一定小于最大值和最小值的差

接着先使用一次二分,找可能的中位数的值,日常  while(s<e){}   走起

第一次二分找到mid=(s+e)/2 = 2;

假设有m个差大于要求的3   :    比如1 2 3 4 5 6这样6个数  题目要求的中位数是第三个数

说明这个mid太小了,答案在mid到e的范围内,所以让s=mid;

否则,答案肯定在s到mid的范围内,让e=mid;

题目第一个例子的第一次二分,mid=2;

那么4-2    4-1   3-1 这三个差要大于等于mid值,即不满足3>3

所以答案在s=0到mid=2的范围内,以此类推,二分下去

最后二分终止时就可以找到正确答案。

但是不明白这题为什么在s=mid;或者e=mid的地方不用加1减1都可以不卡死循环

下面贴我自己手打的代码 464K 688MS

代码语言:javascript
复制
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
vector<int>v;
int xiangshu, n;
bool dd(int x) {
	int sum = 0;
	for (int i = 0; i < n; i++) {
		sum += v.end() - lower_bound(v.begin(), v.end(), v[i] + x) ;
	}
	if (sum > xiangshu) return true;
	return false;
}
int main()
{
	int num;
	while (~scanf_s("%d", &n)) {
		v.clear();
		for (int i = 0; i < n; i++) {
			scanf_s("%d", &num);
			v.push_back(num);
		}
		xiangshu = n * (n - 1) / 2;
		if (xiangshu & 1) {
			xiangshu = xiangshu / 2;
		}
		else {
			xiangshu /= 2;
		}
		sort(v.begin(), v.end());
		int s = 0, e = v[n - 1] - v[0] + 1;
		while (s < e - 1) {
			int mid = (s + e) / 2;
			if (dd(mid)) {
				s = mid ;
			}
			else {
				e = mid;
			}
		}
		printf("%d\n", s);
	}
	return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-07-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档