POJ

来源:互联网 发布:网上配眼镜靠谱吗 知乎 编辑:程序博客网 时间:2024/06/16 19:59

问题描述

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

121 12 12 22 32 43 13 23 83 95 15 255 10

Sample Output

3-99993312100007-199987-99993100019200013-399969400031-99939

分析:

这个问题也是典型的查找第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>using namespace std;typedef long long ll;ll N,M;ll f(ll i, ll j){    return i * i + 100000 * i + j * j - 100000 * j + i * j;}bool C(ll d){    ll cnt = 0;    for(int j=1; j<N+1; j++)    {        ll lb = 0, ub = N+1;        while(ub - lb > 1)        {            ll i = (ub + lb) / 2;            if(f(i, j) < d)            {                lb = i;            }               else ub = i;        }         cnt += lb;    }    return cnt < M;}void solve(){    ll lb = -100000*N, ub = N * N + 100000 * N + N * N + N * N;    while(ub - lb > 1)    {        ll mid = (lb + ub) / 2;        if(C(mid)) lb = mid;        else ub = mid;    }    printf("%lld\n", lb);}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&N, &M);        solve();        }       return 0;}
1 0
原创粉丝点击