您的位置:首页 > 其它

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

2015-09-04 20:18 330 查看
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

POJ Founder Monthly Contest – 2008.08.31, windy7926778

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

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

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<math.h>
#include<stdlib.h>
using namespace std;
#define inf 1<<30
#define ll long long
#define N 50006
ll n,m;
ll cal(ll i,ll j){
return i*i+100000*i+j*j-100000*j+i*j;
}
bool solve(ll mid){
ll cnt=0;
for(ll j=1;j<=n;j++){
ll low=1;
ll high=n+1;
ll tmp=(low+high)>>1;
while(low<high){
ll ans=cal(tmp,j);
if(ans>=mid){
high=tmp;
}
else{
low=tmp+1;
}
tmp=(low+high)>>1;
}
cnt+=tmp-1;
}
if(cnt>=m) return true;
return false;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){

scanf("%I64d%I64d",&n,&m);
ll low=-1e12;
ll high=1e12;
ll mid=(low+high)>>1;
while(low<high){
if(solve(mid)){
high=mid;
}
else{
low=mid+1;
}
mid=(low+high)>>1;
}
printf("%I64d\n",mid-1);

}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: