• 二分套二分_poj3685


    问题描述

    Given a N × N matrix A, whose element in the i-th row and j-th column Aij is an number that equals i^2 + 100000 × i + j^2 - 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Sample Output

    3
    -99993
    3
    12
    100007
    -199987
    -99993
    100019
    200013
    -399969
    400031
    -99939
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    分析:

    这个问题也是典型的查找第k大值,所以依然用二分法,和POJ-3579这题有着异曲同工之处。 
    分析一下这个式子i^2 + 100000 × i + j^2 - 100000 × j + i × j 
    我们发现如果定j的话,式子随着i单调递增,那么这样就可以先循环j,内部用二分i来统计小于d的共有多少个数,然后最后判断是否小于M,小于M就是d弄的小了。二分套二分

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    using namespace std;
    ll n,m;
    ll f(ll x,ll y)
    {
        return x*x+100000*x+y*y-100000*y+x*y;
    
    }
    bool c(ll x)
    {
        ll sum=0;
        for(int j=1;j<=n;j++)
        {
    
            ll left=0,right=n+1;
            while(right-left>1)
            {
                ll Mid=(right+left)/2;
                if(f(Mid,j)<x)left=Mid;
                else right=Mid;
            }
            sum+=left;
        }
        return sum<m;
    }
    void solve()
    {
        ll l=-100000*n,r=n * n + 100000 * n + n * n + n * n;
        while(r-l>1)
        {
            ll mid=(l+r)/2;
            if(c(mid))l=mid;
            else r=mid;
        }
       printf("%lld
    ",l);
    }
    int main()
    {
        int tt;
        scanf("%d",&tt);
        while(tt--){
        scanf("%d%d",&n,&m);
    
        solve();
        }
        return 0;
    }
    

      

  • 相关阅读:
    Create a toolwindow for the VBA editor with .NET(C#).
    批量采集世纪佳缘会员图片及winhttp异步采集效率
    写了一个Windows API Viewer,提供VBA语句的导出功能。提供两万多个API的MSDN链接内容的本地查询
    mysql主从复制
    windows实现MySQL主从复制
    理解“业务逻辑”的含义
    数据库主从复制与读写分离(了解)
    windows下npm安装vue
    phpstorm中配置真正的远程调试(xdebug)
    PHP常量详解:define和const的区别
  • 原文地址:https://www.cnblogs.com/passion-sky/p/9065728.html
Copyright © 2020-2023  润新知