• Matrix [POJ3685] [二分套二分]


    Description

    有一个N阶方阵 第i行,j列的值Aij =i2 + 100000 × i + j2 - 100000 × j + i × j,需要找出这个方阵的第M小值.

    Input

    第一行输入T代表测试组数.
    每个测试用例包含2个数字N,M表示在N阶方阵找出第M大值, N(1 ≤ N ≤ 50,000) and M(1 ≤ M≤ N × N). 每两个测试用例之间可能有空行

    Output

    输出方阵的第M小值

    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

    Analysis

    在二分m的大小之后,再次二分统计小于等于m的个数,但是可以有两个方向

    我真的好蠢,调了一个下午...方向不太好

    下面两个函数是等价的,一个关于i,一个关于j

    f(i)=i2+(100000+j)×i+j2-100000×j 

    f(j)=j2+(i-100000)×j+i2+100000×i)

    我们发现第一个函数的对称轴小于0,也就是在[1,n]的区间上是单调的,而第二个函数对称轴是有可能在[1,n]区间里的,所以要分类讨论

    我就是写的第二种...所以有一点...

    Code

     1 #include<set>
     2 #include<map>
     3 #include<queue>
     4 #include<stack>
     5 #include<cmath>
     6 #include<cstdio>
     7 #include<cstring>
     8 #include<iostream>
     9 #include<algorithm>
    10 #define RG register ll
    11 #define rep(i,a,b)    for(RG i=a;i<=b;++i)
    12 #define per(i,a,b)    for(RG i=a;i>=b;--i)
    13 #define ll long long
    14 #define inf (1<<29)
    15 #define cal(x,y) (y*y+(x-100000ll)*y+x*x+100000ll*x)
    16 using namespace std;
    17 ll T;
    18 ll n,m;
    19 inline ll read()
    20 {
    21     ll x=0,f=1;char c=getchar();
    22     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    23     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    24     return x*f;
    25 }
    26 
    27 ll check(ll lim)
    28 {
    29     ll cnt=0;
    30     rep(i,1,n)
    31     {
    32         ll AOF=(100000ll-i)/2ll;//对称轴
    33         if(n<=AOF)
    34         {
    35             ll l=1,r=n,mid,num,ans=0;
    36             while(l<=r)
    37             {
    38                 mid=l+r>>1,num=cal(i,mid);
    39                 if(num>lim)    ans=mid,l=mid+1;
    40                 else        r=mid-1;
    41             }
    42             cnt+=n-ans;
    43         }
    44         else
    45         {
    46             ll l=1,r=AOF,mid,num,ans=0;
    47             while(l<=r)
    48             {
    49                 mid=l+r>>1,num=cal(i,mid);
    50                 if(num>lim)    ans=mid,l=mid+1;
    51                 else        r=mid-1;
    52             }
    53             cnt+=AOF-ans;//bug!
    54             
    55             l=AOF+1,r=n,mid,num,ans=AOF;
    56             while(l<=r)
    57             {
    58                 mid=l+r>>1,num=cal(i,mid);
    59                 if(num<=lim)    ans=mid,l=mid+1;
    60                 else            r=mid-1;
    61             }
    62             cnt+=ans-AOF; 
    63         }
    64     }
    65     return cnt>=m;
    66 }
    67 
    68 int main()
    69 {
    70     T=read();
    71     while(T--)
    72     {
    73         n=read(),m=read();
    74         ll l=cal(1ll,n),r=max(cal(n,1ll),cal(n,n)),mid,ans;
    75         while(l<=r)
    76         {
    77             mid=l+r>>1;
    78             if(check(mid))    ans=mid,r=mid-1;
    79             else            l=mid+1;
    80         }
    81         printf("%lld
    ",ans);
    82     }
    83     return 0;
    84 }
    View Code
  • 相关阅读:
    一个帖子掌握android所有控件、ProgressBar 、Android 动画效果、SQLite、四大组件、Android多媒体(转
    Android开发交流群
    我的程序里 《我的歌声里》程序员版
    《老罗Android开发视频教程安卓巴士》(Android 开发)
    #百度360大战# 我为什么要支持360
    安卓巴士移动开发者周刊第九期
    水杯题的非常好的解释
    [LeetCode] Jump Game
    [LeetCode] Longest Common Prefix
    [CareerCup][Google Interview] 寻找动态的中位数
  • 原文地址:https://www.cnblogs.com/ibilllee/p/9269461.html
Copyright © 2020-2023  润新知