知识点:二分
这个题和上个题基本是一模一样,是求第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;
}