POJ3685 Matrix

知识点:二分

这个题和上个题基本是一模一样,是求第K大,如果直接求那么空间和时间都不行,那么还是用二分答案,把直接求解转化为判定问题,二分第K大的值,判定函数就是,当前小于等于二分值的数的个数大于等于题目给的K,那么返回真,否者返回假,然后这个题判定函数里面还要使用二分,然后通过简单的数学推导,一行上面的数字不具有单调性,不能用二分,列上的数字有单调性,也就是同一列上面的数字是单调递增的,那么我们就遍历列,每一列上面找小于等于二分值的数的个数就行了,然后累加一块儿就行了,这个题需要注意的是第K大这个K可能超int的范围,这个要看数据范围的时候就想到

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 1e5;

ll n, m;

inline ll calc(ll r, ll c) {
	return r * r + N * r + c * c - N * c + r * c;
}

bool check(ll x) {
	ll cnt = 0;
	for (ll i = 1; i <= n; i++) {
		ll l = 1, r = n + 1;
		while (l < r) {
			ll mid = (l + r) >> 1;
			if (calc(mid, i) > x) r = mid;
			else l = mid + 1;
		}
		cnt += l - 1;
	}
	return cnt >= m;
}

int main() {
	int T;
	cin >> T;
	while (T--) {
		cin >> n >> m;
		long long l = -1e10, r = 1e11;
		while (l < r) {
			long long mid = (l + r) >> 1;
			if (check(mid)) r = mid;
			else l = mid + 1;
		}
		cout << l << '\n';
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值