poj3685 二分套二分

二分经典题,

注意INF不能开太小(WA),也不能开太大(会T)。。

/*
f(i)=i*i+(100000+j)*i-(100000-j)*j
f(i)是对i的递增函数,外层二分mid答案,内层枚举j二分i寻找有多少<=mid 
复杂度O(lognlogn * n) 
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 50050 
#define ll long long 
#define INF 1000000000000

using namespace std;

long long n,m,t;

inline long long f(ll i,ll j){return i*i+100000*i+j*j-100000*j+i*j;}

inline long long check(ll x){//枚举每个j,二分找使f(i)<=x的个数,并累加 
    ll res=0; 
    for(ll j=1;j<=n;j++){
        ll l=1,r=n,mid,ans=0;
        while(l<=r){
            mid=l+(r-l)/2;
            if(f(mid,j)<=x) //值比x小 
                ans=mid,l=mid+1;
            else r=mid-1; //值比x大 
        }
        res+=ans;
    }
    return res;
}

int main(){
    scanf("%I64d",&t);
    while(t--){
        scanf("%I64d%I64d",&n,&m);
        ll l=-(ll)INF,r=INF,mid,ans=0;
        while(l<=r){
            mid=l+(r-l)/2;
            if(check(mid)<m)//mid取值小 
                l=mid+1;
            else ans=mid,r=mid-1;
        }
        printf("%I64d\n",ans);
    }
} 

 

posted on 2018-12-19 10:59  zsben  阅读(132)  评论(0编辑  收藏  举报

导航