您的位置:首页 > 其它

POJ - 3685 Matrix(二分/查找第k大值)

2017-04-26 23:24 302 查看
问题描述

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


Sample Output

3
-99993
3
12
100007
-199987
-99993
100019
200013
-399969
400031
-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;

4000
}
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: