POJ 3685 二分套二分

Posted #WoNderlAnd#

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3685 二分套二分相关的知识,希望对你有一定的参考价值。

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 ≤ MN × 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

Sample Output

3
-99993
3
12
100007
-199987
-99993
100019
200013
-399969
400031
-99939

 


 

刚看到题的时候依旧一脸懵逼,不知道从哪开始下手,还是向大佬的题解妥协了

式子是关于i单调递增的(求偏导……都会得……嗯……)然后,找突破口

先二分答案x,然后二分的去找每行<x的个数,根据小于x的个数来调整x的大小。。。——二分套二分……

#include<iostream>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<algorithm>
typedef long long ll;
using namespace std;
ll n, m,t;
bool judge(ll a, ll b,ll c)
{
    return (a*a + 100000*a + b*b - 100000*b + a*b)<c;
}
bool C(ll x)
{
    ll crt = 0;
    for (int i = 1; i <= n; i++)  //i从1开始
    {
        ll le = 0, r = n + 1;
        while (le<r-1)  //找没行多少个小于mid的
        {
            ll mi = (r + le) /2 ;
            if (judge(mi, i, x)) le = mi;
            else r = mi;
        }
        crt += le;  
    }
    return crt < m;
}
int main()
{
       scanf("%lld", &t);
        while (t--)
        {
            scanf("%lld%lld",&n, &m);
            ll l = -100000*n, h = 3*n*n+100000*n;  //不懂为什么换成inf就WA
            while(h-l>1)
            {
                ll mid = (h + l) / 2;
                if (C(mid)) l = mid;
                else h = mid;
            }
            printf("%lld\n", l);
        }
    return 0;
}

 

以上是关于POJ 3685 二分套二分的主要内容,如果未能解决你的问题,请参考以下文章

POJ 3685 二分套二分

poj3685 Matrix

POJ-3579 Median---二分第k大(二分套二分)

POJ 3685 二分

POJ3685 Matrix(嵌套二分)

POJ 3579 3685(二分-查找第k大的值)