POJ - 3685 Matrix (二分搜索:查找第k大的值)

http://poj.org/problem?id=3685

题意:

定义一个N*N矩阵:Aij =  i2 + 100000 × i + j2 - 100000 × j + i × j。

求第M大的值。

N(1 ≤ N ≤ 50,000) and M(1 ≤ M ≤ N × N).

——————————————————————————

跟这题有点类似: POJ - 3685 Median(二分搜索,查找第K大的值)

这个矩阵有个规律:每列单调递增。可以根据这个分别对每一列进行二分搜索,求出比x小的个数,得出排在第几位。x的枚举也是通过一个二分搜索得出。

总的时间复杂度为:O(log(MAX_Aij)*N*log(N))。

这里的MAX_Aij懒得算了,就直接用long long的上下限吧……= =。

这题因为二分搜索的上下界出了许多问题,反复调试了很久,感觉while(r - l > 1)这种方法确实不太好。


#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAX_N = 1e5;
long long  N, M;
inline long long getnum(long long  i,long long j)
{
	return i*i + 100000 * i + j*j - 100000 * j + i * j;
}
bool C(long long x)
{
	long long cnt = 0;
	for(int j = 1; j <= N; j++)
	{
		if(x > getnum(N, j))
			cnt += N;
		else
		{
			int l = 0, r = N;
			while(r - l > 1)
			{
				int mid = (l+r)/2;
				if(getnum(mid, j) >= x)
					r = mid;
				else
					l = mid;
			}
			//cnt += N - r + 1;
			cnt += r - 1;
		}
	}
	//return cnt > N*N-M;
	return cnt >= M;		//左
}
void solve()
{
//#define DEBUG
#ifdef DEBUG
	for(int i = 1; i <= N; i++)
		for(int j = 1; j <= N; j++)
			printf(j == N ? "%10lld\n": "%10lld ", getnum(i, j));
#endif

	if(N == 1)
	{
		printf("3\n");
		return ;
	}
	long long l = -0x3fffffffffffffff, r = 0x3fffffffffffffff;
	while(r - l > 1)
	{
		long long mid = (l+r)/2;
		if(C(mid))
			r = mid;
		else
			l = mid;
	}
	printf("%lld\n", l);
}
			
int main()
{
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
	int T;
	scanf("%d", &T);
	while(T--)
	{
		scanf("%lld%lld", &N, &M);
		solve();
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值