/*
translation:
给出一个矩阵,其中每项的值为:i*i + C*i + j*j - C*j + i*j;(i,j分别为所在的行和列)。求其第m小的数字
solution:
二分查找k小数字
观察发现矩阵的规律是从上倒下递增,从左到右递减。可以根据这个规律来二分查找有几个小于当前给出的值。详见代码
note:
date:
2016.11.5
*/
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 50000 +5;
const int C = 1e5;
typedef long long ll;
ll n, m;
ll f(ll i, ll j)
{
return i*i + C*i + j*j - C*j + i*j;
}
bool check(ll mid)
{
ll cnt = 0;
for(ll j = 1; j <= n; j++){ //对这一列小于等于mid的计数
ll lb = 0, ub = n + 1;
while(ub - lb > 1){
ll i = (lb + ub) >> 1;
if(f(i, j) >= mid) ub = i;
else lb = i;
}
cnt += lb;
}
return cnt >= m;
}
int main()
{
//freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
while(T--){
cin >> n >> m;
ll lb = -C*n, ub = 3*n*n + 100000*n;
while(ub - lb > 1){
ll mid = (ub + lb) >> 1;
if(check(mid)) ub = mid;
else lb = mid;
}
printf("%lld\n", lb);
}
return 0;
}
poj3685(二分查找第k小)
最新推荐文章于 2020-06-05 20:01:15 发布