小红的矩阵
[题目链接](https://www.nowcoder.com/practice/c77b7301464f4cfcacc9492a3c999f65)
思路
给一个 的矩阵,第
行第
列的元素为
,求矩阵中第
小的元素。
暴力行不通
如果 很大,我们没法真的把所有
个元素排序——那可能有
个数。
二分答案
换个角度想:如果我们猜一个值 ,能不能快速算出矩阵里有多少个元素
?
对于第 行,元素分别是
。其中
的有
个。把所有行加起来就得到总个数:
$$
这个求和只需要 时间。
二分框架
- 如果
,说明答案
,缩小右边界。
- 如果
,说明答案
,抬高左边界。
二分范围 ,总复杂度
。
样例演示
,矩阵为:
$$
\begin{bmatrix}
1 & 2 & 3 \\
2 & 4 & 6 \\
3 & 6 & 9
\end{bmatrix}
$$
排序后为 ,第 4 小是
。
二分到 时:第 1 行有
个,第 2 行有
个,第 3 行有
个,总共
,所以答案不超过
。而
时总共
,所以答案就是
。
复杂度
- 时间复杂度:
- 空间复杂度:
代码
#include <bits/stdc++.h>
using namespace std;
int main(){
long long n, m, k;
scanf("%lld%lld%lld", &n, &m, &k);
long long lo = 1, hi = n * m;
while(lo < hi){
long long mid = lo + (hi - lo) / 2;
long long cnt = 0;
for(long long i = 1; i <= n; i++)
cnt += min(mid / i, m);
if(cnt >= k) hi = mid;
else lo = mid + 1;
}
printf("%lld\n", lo);
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long n = sc.nextLong(), m = sc.nextLong(), k = sc.nextLong();
long lo = 1, hi = n * m;
while (lo < hi) {
long mid = lo + (hi - lo) / 2;
long cnt = 0;
for (long i = 1; i <= n; i++)
cnt += Math.min(mid / i, m);
if (cnt >= k) hi = mid;
else lo = mid + 1;
}
System.out.println(lo);
}
}

京公网安备 11010502036488号