題目大意:給定NXN的矩陣,第i行第j列的值Aij = i2 + 100000 × i + j2 - 100000 × j + i × j, N不超過5萬。求第M小的數。
這題仍然是用二分搜索,設C(X):=矩陣中值不小於X的個數不少於K。至於如何判斷命題爲真,可以發現這個等式的值是逐行單調遞增的,所以可以對每一列再進行二分搜索,找出不小於X的個數就可以了。
#include <stdio.h>
#include <vector>
#include <math.h>
#include <string.h>
#include <string>
#include <iostream>
#include <queue>
#include <list>
#include <algorithm>
#include <stack>
#include <map>
using namespace std;
bool CC(long long x, int n, long long k)
{
long long curcount = 0;
int l = -1;
for (int i = 1; i <= n; i++)
{
l = 0;
int r = n + 1;
while (r - l > 1)
{
long long mid = (r + l) / 2;
if (mid * mid + 100000 * mid + i * i - 100000 * i + mid * i >= x)
{
r = mid;
}
else
l = mid;
}
curcount += (n - r + 1);
if (curcount >= k)
{
return true;
}
}
if (curcount < k)
{
return false;
}
else
return true;
}
int main()
{
#ifdef _DEBUG
freopen("d:\\in.txt", "r", stdin);
#endif
int k;
scanf("%d", &k);
for (int i = 0; i < k; i++)
{
long long n, m;
scanf("\n%I64d %I64d\n", &n, &m);
//qsort(values, n, sizeof(int), compp);
long long l = 50000 * (long long)50000 - 100000LL * 50000;
long long r = 50000LL * 50000LL * 3 + 1;
long long k = (long long)n * n - m + 1;
while (r - l > 1)
{
long long mid = (r + l) / 2;
if (CC(mid, n, k))
{
l = mid;
}
else
r = mid;
}
printf("%I64d\n", l);
}
return 1;
}