POJ 3579 3685(二分-查找第k大的值)

POJ 3579

题意

双重二分搜索:对列数X计算∣Xi Xj∣组成新数列的中位数

思路

对X排序后,与X_i的差大于mid(也就是某个数大于X_i + mid)的那些数的个数如果小于N / 2的话,说明mid太大了。以此为条件进行第一重二分搜索,第二重二分搜索是对X的搜索,直接用lower_bound实现。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;

int N;
int CN2 = 0;
int X[100005];
bool C(int x) { // 验证x作为中位数 x = X[j] - X[i] 是否太小
	int cnt = 0;
	for (int i = 0; i<N; ++i) {
		cnt += N - (lower_bound(X + i, X + N, X[i] + x) - X); // 统计差值>=x的个数
	}
	return cnt > CN2 >> 1;
}
void solve() {
	sort(X, X + N);
	CN2 = N*(N - 1) >> 1;
	int lb = 0, ub = 1000000001;
	while (ub - lb > 1) {
		int mid = (ub + lb) >> 1;
		if (C(mid)) lb = mid; // 中位数过小,半闭半开区间[lb, ub)
		else ub = mid;
	}
	printf("%d\n", lb);
}
int main()
{
	while (scanf("%d", &N) == 1) {
		for (int i = 0; i < N; ++i) scanf("%d", X + i);
		solve();
	}
	return 0;
}

POJ 3685

题意:边为n的方阵中,aij=i^2+100000i+j^2-100000j+i*j,求矩阵的第k大数。

思路:需要注意数据规模,特别是1≤M≤N×N,需要64位变量来存

首先来分析下这个函数f(i,j)

可知f(i,j)按行递增(同列),而按列不单调(同行)。

C(x)表示矩阵中<x的元素有多少个。 所以可以一列一列来求有多少个比x小。然后二分求出正好有M?1个数比x小即可。

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll MAX = 1e15;
ll T;
ll N, M;
ll f(ll i, ll j) {
	return i*i + 100000 * (i - j) + i*j + j*j;
}
bool C(ll x) { // 验证x是否过小。。。。这里写成int x调了好久= =
	ll cnt = 0; // cnt 为<x的个数
	for (int j = 1; j <= N; ++j) {
		int lb = 0, ub = N + 1; // (lb, ub)
		while (ub - lb > 1) {
			int mid = (lb + ub) >> 1;
			if (f(mid, j) < x) lb = mid; // 半闭半开区间[lb, ub)
			else ub = mid;
		}
		cnt += lb;
	}
	return cnt < M;
}
void solve() {
	ll lb = f(0, N), ub = f(N, 0) + 1;
	while (ub - lb > 1) {
		ll mid = (ub + lb) >> 1;
		if (C(mid)) lb = mid; // 半闭半开区间[lb, ub)
		else ub = mid;
	}
	cout << lb << endl;
}
int main() {
	cin >> T;
	while (T--) {
		cin >> N >> M;
		solve();
	}
	return 0;
}
时间: 2024-10-13 10:40:34

POJ 3579 3685(二分-查找第k大的值)的相关文章

查找第K大的值

这种题一般是给定N个数,然后N个数之间通过某种计算得到了新的数列,求这新的数列的第K大的值 POJ3579 题意: 用$N$个数的序列$x[i]$,生成一个新序列$b$. 新的序列定义为:对于任意的$ i$,$j$且 $i != j $有$b[] = abs(x[i] - x[j])$ 问新序列的中位数是什么,如果新序列的长度为偶数那么我们定义中位数为排序后第len/2位置的那个数 解法: 相当于问新序列中的第K大的数多少. 注意新数列不可能全都算出来. 二分答案,二分那个第K大的数的值. $x

poj 3579 Median 二分查找与lower_bound

题意: 给n个数,他们两两之间较大数减去较小数总共有n*(n-1)/2个数,要求这些数的中位数. 分析: 两次二分,第一次枚举答案,第二次判断该数是否可能成为中位数. 代码: //poj 3579 //sep9 #include <iostream> #include <algorithm> using namespace std; const int maxN=1e5+10; int a[maxN]; int n,m; int test(int x) { int sum=0; f

poj 3685 Matrix(二分搜索之查找第k大的值)

Description Given a N × N matrix A, whose element in the i-th row and j-th column Aij is an number that equals i2 + 100000 × i + j2 - 100000 × j + i × j, you are to find the M-th smallest element in the matrix. Input The first line of input is the nu

poj 3579 Median (二分搜索之查找第k大的值)

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

poj 1151 Atlantis 二分查找+离散化

Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17464   Accepted: 6654 Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of

POJ 3579 Median 二分+思维

POJ 3579 Median 二分+思维 题意 给你一些数,然后求这些数相互之间差的绝对值,然后绝对值排序,找到中间那个数. 解题思路 我反正一直开始是没有想到这个题竟然可以用二分来做.━━( ̄ー ̄*|||━━. 二分枚举答案,假设枚举值为mid,然后就是在排好序的序列中对每一个num[i]找到在i之后,有多少个大于num[i]+mid的数的个数(数列里的值比num[i]+mid大,说明该值与num[i]作差形成的新数列里的数比中位数mid大),用lower_bound计算所有差值比mid大于

POJ 2104 求序列里第K大 主席树裸体题

给定一个n的序列,有m个询问 每次询问求l-r 里面第k大的数字是什么 只有询问,没有修改 可以用归并树和划分树(我都没学过..囧) 我是专门冲着弄主席树来的 对主席树的建树方式有点了解了,不过这题为什么是在主席树里面这么操作的 还是有点不懂,今天照着模板敲了一遍就打多校了 再研究吧 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using name

hiho week 37 P1 : 二分&#183;二分查找之k小数

P1 : 二分·二分查找之k小数 Time Limit:10000ms Case Time Limit:1000ms Memory Limit:256MB 描述 在上一回里我们知道Nettle在玩<艦これ>,Nettle的镇守府有很多船位,但船位再多也是有限的.Nettle通过捞船又出了一艘稀有的 船,但是已有的N(1≤N≤1,000,000)个船位都已经有船了.所以Nettle不得不把其中一艘船拆掉来让位给新的船.Nettle思考了很久, 决定随机选择一个k,然后拆掉稀有度第k小的船. 已知

hiho#1133 : 二分&#183;二分查找之k小数

#1133 : 二分·二分查找之k小数 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回里我们知道Nettle在玩<艦これ>,Nettle的镇守府有很多船位,但船位再多也是有限的.Nettle通过捞船又出了一艘稀有的船,但是已有的N(1≤N≤1,000,000)个船位都已经有船了.所以Nettle不得不把其中一艘船拆掉来让位给新的船.Nettle思考了很久,决定随机选择一个k,然后拆掉稀有度第k小的船. 已知每一艘船都有自己的稀有度,Nettle现在把所有