POJ-3685 Matrix
Matrix
给出一个\(n * n\)的表格,每个\(A_{ij}\)上有一个数字,其值为\(f(i, j) = i * i + 100000 * i + j * j - 100000 * j + i * j\),问第m小的值是多少
二分套二分
根据函数\(f(i, j)\),我们可以看到,在同一列或同一行中,表格中的值都是一个单调递增或单调递减的
因此我们可以通过\(O(nlogn)\)的时间复杂度,计算出表格中比任意数x小的有多少个数
以上的发现,给judge提供了一个可能,因此我们只要二分答案即可:第m小,代表着表格中小于等于ans的数字有m个,这是一个单调01分布
因此在主函数中通过枚举答案来的得到
二分查询答案,judge函数中也是一个二分询问,所以是二分套二分
时间复杂度:\(O(nlog^2n)\)
#include <cstdio>
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;
}
ll query(ll x)
{
ll ans = 0;
for(ll i=1; i<=n; i++)
{
ll l = 1, r = n + 1;
while(l < r)
{
ll mid = l + r >> 1;
if(f(mid, i) <= x)
l = mid + 1;
else
r = mid;
}
ans += l;
}
return ans - n;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%lld%lld", &n, &m);
ll l = -1e17, r = 1e17;
while(l < r)
{
ll mid = l + (r - l) / 2;
if(query(mid) < m)
l = mid + 1;
else
r = mid;
}
printf("%lld\n", l);
}
return 0;
}