
矩阵:N阶矩阵Aij= i2 + 100000 × i + j2 – 100000 × j + i × j,求第M小的元素。
3.1不光是查找值!“二分搜索”
查找第k大的值
观察 i2 + 100000 × i + j2 – 100000 × j + i × j这个表达式,发现是对i递增的,于是利用这个特性进行二分搜索,统计比mid小的数的个数,接着以此个数是否小于M(小于的话说明mid太小了)进行外层的二分搜索。
#ifndef ONLINE_JUDGE
#pragma warning(disable : 4996)
#endif
#include <iostream>
using namespace std;
typedef long long LL;
LL T, N, M;
LL f(const LL& i, const LL& j)
{
return i * i + 100000 * i + j * j - 100000 * j + i * j;
}
// mid 是否小于第M小的数
bool is_less(const LL& mid)
{
LL less_count = 0; // 比mid小的数的个数
for (int j = 1; j < N + 1; ++j)
{
// 当然不能这么搜啦
// for (int i = 1; i < N + 1; ++i)
// {
//
// }
int lb = 0, ub = N + 1;
while (ub - lb > 1)
{
int i = (ub + lb) >> 1;
if (f(i, j) < mid)
{
lb = i;
}
else
{
ub = i;
}
}
less_count += lb;
}
return less_count < M;
}
///////////////////////////SubMain//////////////////////////////////
int main(int argc, char *argv[])
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
cin >> T;
while (T--)
{
cin >> N >> M;
LL lb = -100000 * N, ub = N * N + 100000 * N + N * N + N * N;
while (ub - lb > 1)
{
LL mid = (ub + lb) >> 1;
if (is_less(mid))
{
lb = mid;
}
else
{
ub = mid;
}
}
cout << lb << endl;
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
system("out.txt");
#endif
return 0;
}
///////////////////////////End Sub//////////////////////////////////
| 12843163 | hankcs | 3685 | Accepted | 216K | 907MS | C++ | 1331B | 2014-05-06 00:01:55 |
码农场
楼主您好,最后lb的值为什么一定符合 i * i + 100000 * i + j * j – 100000 * j + i * j 的形式呀?感谢感谢!!