题目描述:
给出一个矩阵,矩阵每个点(i,j)的数值是i*i+100000*i+j*j-100000*j+i*j。求出第m大的数。
大致思路:
数据范围略大,所以采用二分的想法,二分一个数值x,每次统计比他大的数的个数,在统计过程中,对于每一列二分行号j,确定这一列比x大的数目。这样整体算法就是nlogn*logn的了。
代码:
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const ll inf = 1LL << 50;
ll n,m;
ll f(ll i,ll j) {
return i*i + 100000*i + j*j - 100000*j + i*j;
}
bool c(ll x) {
ll sum = 0;
for (int i = 1; i <= n; i++) {
ll l = 0,r = n+1;
ll tmp = n + 1;
while (r - l > 1) {
ll mid = (l + r) / 2;
if (f(mid,i) >= x) {
r = mid;
}
else l = mid;
}
sum += l;
}
return sum >= m;
}
int main() {
int T;
cin>>T;
while (T--) {
scanf("%I64d%I64d",&n,&m);
ll l = -inf,r = inf;
ll ans = 0;
while (r - l > 1) {
ll mid = (l + r) / 2;
if (c(mid)) {
r = mid;
}
else l = mid;
}
printf("%I64d\n",l);
}
}