• poj 3685 Matrix(二分搜索之查找第k大的值)


    Description

    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

    Sample Output

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

    Source

     

     题目大意:题目意思很简单。这个题目乍一看,先打n为比较小例如8的表,会觉得很有规律,大小规律是从右上往左下依次增大,但是这个规律到n为5*10^4就不一定保持了。

               解题思路:有一个规律是看得见的,j不变i增大函数值也在增大。根据这个可以对这n列二分得到<x的值,同样所求的x也是可以二分慢慢靠近最后的结果,我处理得到最后的结果是个数为m+1的最小值,所以最后mid-1即为答案。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<math.h>
     6 #include<stdlib.h>
     7 using namespace std;
     8 #define inf 1<<30
     9 #define ll long long
    10 #define N 50006
    11 ll n,m;
    12 ll cal(ll i,ll j){
    13     return i*i+100000*i+j*j-100000*j+i*j;
    14 }
    15 bool solve(ll mid){
    16     ll cnt=0;
    17     for(ll j=1;j<=n;j++){
    18         ll low=1;
    19         ll high=n+1;
    20         while(low<high){
    21             ll tmp=(low+high)>>1;//另外的写法
    22             ll ans=cal(tmp,j);
    23             if(ans>=mid){
    24                 high=tmp;
    25             }
    26             else{
    27                 low=tmp+1;
    28             }
    29         }
    30         cnt+=low-1;//另外的写法
    31     }
    32     if(cnt>=m) return true;
    33     return false;
    34 }
    35 int main()
    36 {
    37     int t;
    38     scanf("%d",&t);
    39     while(t--){
    40 
    41         scanf("%I64d%I64d",&n,&m);
    42         ll low=-1e12;
    43         ll high=1e12;
    44 
    45         while(low<high){
    46             ll mid=(low+high)>>1;//另外的写法
    47             if(solve(mid)){
    48                 high=mid;
    49             }
    50             else{
    51                 low=mid+1;
    52             }
    53         }
    54         printf("%I64d
    ",low-1);//另外的写法
    55 
    56     }
    57     return 0;
    58 }
    View Code

    另外的写法,试比较

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<math.h>
     6 #include<stdlib.h>
     7 using namespace std;
     8 #define inf 1<<30
     9 #define ll long long
    10 #define N 50006
    11 ll n,m;
    12 ll cal(ll i,ll j){
    13     return i*i+100000*i+j*j-100000*j+i*j;
    14 }
    15 bool solve(ll mid){
    16     ll cnt=0;
    17     for(ll j=1;j<=n;j++){
    18         ll low=1;
    19         ll high=n+1;
    20         ll tmp=(low+high)>>1;
    21         while(low<high){
    22             ll ans=cal(tmp,j);
    23             if(ans>=mid){
    24                 high=tmp;
    25             }
    26             else{
    27                 low=tmp+1;
    28             }
    29             tmp=(low+high)>>1;
    30         }
    31         cnt+=tmp-1;
    32     }
    33     if(cnt>=m) return true;
    34     return false;
    35 }
    36 int main()
    37 {
    38     int t;
    39     scanf("%d",&t);
    40     while(t--){
    41 
    42         scanf("%I64d%I64d",&n,&m);
    43         ll low=-1e12;
    44         ll high=1e12;
    45         ll mid=(low+high)>>1;
    46         while(low<high){
    47             if(solve(mid)){
    48                 high=mid;
    49             }
    50             else{
    51                 low=mid+1;
    52             }
    53             mid=(low+high)>>1;
    54         }
    55         printf("%I64d
    ",mid-1);
    56 
    57     }
    58     return 0;
    59 }
    View Code
  • 相关阅读:
    2018全球最强物联网公司榜单揭晓
    物联网
    kalman滤波
    自动驾驶
    CAN总线基础
    Linux系统下x86和ARM的区别有哪些?
    算法课笔记系列(七)—— 平摊分析Amortized Analysis
    深入理解Linux内存分配
    linux内核--自旋锁的理解
    DMA(直接存储器存取)
  • 原文地址:https://www.cnblogs.com/UniqueColor/p/4782278.html
Copyright © 2020-2023  润新知