POJ3685-Matrix
题目大意:给出一个n*n
的矩阵a
,且
1
| a[i][j] = i * i + 100000 * i + j * j - 100000 * j + i * j
|
求矩阵中第m小的元素的值。
二分枚举可能的第m小元素值x,判断比它小的元素是否少于m个,如果是,则第m小的元素值小于等于x,否则第m小的元素值大于x。
怎么判断比x小的元素是否少于m个?注意到:当j一定时,a[i][j]
的值随i的增大而增大。因此对于每一个j,二分查找小于x的最大a[i][j]
。若这个满足条件的最大a[i][j]
是a[t][j]
,那么a[][j]
中就一共有t个比x小的元素。对每一个j找一遍这个t,加起来,就是整个矩阵中比x小的元素个数了
于是可以写出代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <map> #include <set> #include <queue> #include <stack> #include <cctype> using namespace std; long long n, m;
bool C(long long x) { long long sum = 0, j; for (j = 1; j <= n; j++) { long long l = 0, r = 1e5, md; while (r - l > 1) { md = l + ((r - l) >> 1); if (md * md + 100000 * md + j * j - 100000 * j + md * j < x) l = md; else r = md; } sum += l; } return sum < m; } int main() { int _; scanf("%d", &_); while (_--) { scanf("%lld%lld", &n, &m); long long l = -1e10, r = 1e10, md; while (r - l > 1) { md = l + ((r - l) >> 1); if (C(md)) l = md; else r = md; } printf("%lld\n", l); } return 0; }
|
但这个代码连样例都过不了。因为函数C中的二分可能会使l找到数组右边界的地方导致错误。所以应该这么写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <map> #include <set> #include <queue> #include <stack> #include <cctype> using namespace std; long long n, m;
bool C(long long x) { long long sum = 0, j; for (j = 1; j <= n; j++) { long long l = 0, r = 1e5, md; while (r - l > 1) { md = l + ((r - l) >> 1); if (md <= n && md * md + 100000 * md + j * j - 100000 * j + md * j < x) l = md; else r = md; } sum += l; } return sum < m; } int main() { int _; scanf("%d", &_); while (_--) { scanf("%lld%lld", &n, &m); long long l = -1e10, r = 1e10, md; while (r - l > 1) { md = l + ((r - l) >> 1); if (C(md)) l = md; else r = md; } printf("%lld\n", l); } return 0; }
|