http://poj.org/problem?id=3685
N阶矩阵,Aij= i^2 + 100000 × i + j^2 – 100000 × j + i × j,求第M小的元素。
双重二分。
(1)先二分枚举比 mid 小的个数。
(2)观察 式子【 i^2 + 100000 × i + j^2 – 100000 × j + i × j】,它与呈i单调关系,所以每次枚举J,二分i,统计该列小于mid的个数。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
long long t,n,m;
long long ans;
long long f(long long i,long long j){
return i*i+100000*i+j*j-100000*j+i*j;
}
bool Less(long long mid){
long long cnt=0; //每列比mid小的个数
for (long long j=1;j<=n;j++){
long long l=0,r=n+1;
while (r-l>1){
long long i=(r+l)>>1;
if (f(i,j)<mid) l=i;
else r=i;
}
cnt+=l;
}
return cnt<m;
}
int main(){
cin >> t;
while (t--){
cin >> n >> m;
long long l=-100000*n,r=n*n+100000*n+n*n+n*n;
while (r-l>1){
long long mid=(r+l)>>1;
if (Less(mid)) l=mid;
else r=mid;
}
cout << l << endl;
}
}