题意:N阶矩阵Aij= i2 + 100000 × i + j2 – 100000 × j + i × j,求第M小的元素。
思路:双重二分
- 考虑到,aij是跟着i递增的,所以i可以作为一个二分搜索
- 统计比 mid小的个数
- 如果个数小于 m的话 mid太小
- 反之 mid太大
解决问题的代码:
#include <iostream> #include <stdio.h> #include <algorithm> #include <math.h> using namespace std; typedef long long ll; ll t, n, m; ll f(ll i, ll j) { return i * i + 100000 * i + j * j - 100000 * j + i * j; } bool solve(ll mid) { ll less = 0; for (int j = 1; j <= n; j++) { int lb = 0, ub = n + 1; while (ub - lb > 1) { int i = (ub + lb) / 2; if (f(i, j) <mid) { lb = i; } else ub = i; } less += lb; } return less < m; } int main() { scanf("%lld", &t); while (t--) { scanf("%lld%lld", &n, &m); ll lb = -100000 * n; ll ub = n * n + 100000 * n + n * n + n * n; while (ub - lb > 1) { ll mid = (ub + lb) / 2; if (solve(mid)) lb = mid; else ub = mid; } printf("%lld\n", lb); } return 0; }