POJ 3685 Matrix (二分套二分)

题目

Given a N × N matrix A, whose element in the i-th row and j-th column Aij is an number that equals i2 + 100000 × i + j2 - 100000 × j + i × j, you are to find the M-th smallest element in the matrix.

Input
The first line of input is the number of test case.
For each test case there is only one line contains two integers, N(1 ≤ N ≤ 50,000) and M(1 ≤ M ≤ N × N). There is a blank line before each test case.

Output
For each test case output the answer on a single line.

Sample Input
12

1 1

2 1

2 2

2 3

2 4

3 1

3 2

3 8

3 9

5 1

5 25

5 10

题解

先开始上去肯定还是找规律的,但是在推了一下后面发现,其实并不包含某种单调性。考虑一下而二分答案,二分mid为答案值,然后因为在i或者j固定的时候答案是单调变化的,所以我们在一个列里面去二分一下num,把num相加,看下是否大于k值,继续二分找到答案即可。

代码实现

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
ll n,k;
ll f (ll x,ll y) {
    return x*x+100000*x+y*y-100000*y+x*y;
}

bool check (ll x) {
  ll num=0;
  for (ll i=1;i<=n;i++) {
    ll l=0,r=n,mid;
    while (l<r) {
      mid=(l+r+1)/2;
      if (f (mid,i)<=x) l=mid;
      else r=mid-1;
    }
    num+=l;
  }
  return num>=k;
}

int main () {
  int t;
  scanf ("%d",&t);
  while (t--) {
    scanf ("%lld%lld",&n,&k);
    ll l=-1e12,r=1e12;
    ll ans;
    while (l<r) {
      ll mid=(l+r)>>1;
      if (check (mid)) r=mid;
      else l=mid+1;
    }
    printf ("%lld\n",l);
  }
  return 0;
}
posted @ 2020-11-02 19:38  Luglucky  阅读(155)  评论(0编辑  收藏  举报