Matrix(for hw)---二分搜索

本文介绍了二分查找算法的特点及适用场景,并通过一个具体的矩阵问题展示了如何利用二分查找解决大规模数据查找的问题。该算法适用于查找密集但不常变动的有序列表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

前提:有序数组!
下面提供一段二分查找实现的伪代码:

BinarySearch(max,min,des)
mid-<(max+min)/2
while(min<=max)
mid=(min+max)/2
if mid=des then
return mid
elseif mid >des then
max=mid-1
else
min=mid+1
return max
Description

Given a N × N matrix A, whose element in the i-th row and j-th column Aij is an number that equals i2 + 100000 × i + j2 - 100000 × j + i × j, you are to find the M-th smallest element in the matrix.

Input

The first line of input is the number of test case.
For each test case there is only one line contains two integers, N(1 ≤ N ≤ 50,000) and M(1 ≤ M ≤ N × N). There is a blank line before each test case.

Output

For each test case output the answer on a single line.

Sample Input

12

1 1

2 1

2 2

2 3

2 4

3 1

3 2

3 8

3 9

5 1

5 25

5 10
Sample Output

3
-99993
3
12
100007
-199987
-99993
100019
200013
-399969
400031
-99939

hint:

Hint:

1.注意long long

2.2500000000个数直接排序的话是没有算法能在1秒内完成的

3.观察矩阵会发现固定j,元素的值会随i递增,因此如果我们知道了某个值K,可以对每一列采用二分查找的方法在O(NlogN)的时间内找出矩阵中有多少个数小于K

4.显然矩阵中小于K的元素的个数也是随K递增的,因此用跟3相同思想的某种方法可以使整个算法的时间复杂度维持在O(TNlogNlogL)以内,其中L是矩阵的值域大小

5.师兄只能提示到这里了←_←

6.注意long long,因为真的很容易出错所以提醒两遍

#include <stdio.h>
#define f(i, j)  i*i + 100000 * i + j * j - 100000 * j + i * j
//能够大大增加程序的效率!!!
#define maxn 1e12
#define minn -1e12
typedef long long ll;
//此题大量使用long long类型,因而可以宏定义,简化程序。
int n, m;
//使用全局变量来串连函数和main

ll search(ll x) {
    int i;
    ll num = 0;
    ll max, min, mid;
    for (i = 1; i <= n; i++) {
        max = n + 1, min = 1;
        mid = (max + min) >> 1;
        while (max > min) {
            if (f(mid, i) >= x) {
                max = mid;
            } else {
                min = mid + 1;
            }
            mid = (max + min) >> 1;
        }
        num += mid - 1;
    }
    return num;
}
//用来计算在矩阵中比x小的数有多少个

int main() {
    int total;
    scanf("%d", &total);
    while (total--) {
        scanf("%d%d", &n, &m);
        ll high = maxn;
        ll low = minn;
        ll mid = (high + low)>>1;
        //思路是用取一个可能的最大值和一个可能的最小值和矩阵中的值进行二分搜索
        while (low < high) {
            if (search(mid) >= m) {
                high = mid;
            } else {
                low = mid + 1;
            }
            mid = (low + high) >> 1;
        }
        printf("%lld\n", mid - 1);
    }
    return 0;
}
<think>好的,用户现在想了解二维滑动窗口算法的基本概念和工作原理,需要给出定义和简明介绍。根据之前的对话历史,用户之前已经询问过一维和二维滑动窗口算法的区别,现在更深入地问二维的具体内容。首先,我需要回忆之前提供的二维滑动窗口的信息,比如在矩阵中扩展窗口维度,行预处理和列滑动,以及应用场景如最大子矩阵和。同时要注意用户提供的引用,虽然引用中的内容可能不完全相关,但需要检查是否有可用之处。引用1提到二维情况下的L1正则化,可能与当前问题无关。引用2关于边界框调整,可能涉及窗口的表示,但不确定是否直接相关。引用3关于卷积结果的三维张量,可能和图像处理中的滑动窗口应用有关联,但用户的问题更偏向算法而非深度学习。 接下来,要确保回答符合系统指令:数学公式用$...$或$$...$$,正确使用LaTeX,中文回答,生成相关问题,引用标注自然。同时,结构要清晰,分点说明。需要定义二维滑动窗口算法,说明其工作原理,可能涉及预处理步骤(如行或列的前缀和),动态调整窗口的方法,以及时间复杂度。可以举例子,比如计算固定大小的子矩阵和,或者最大子矩阵和问题。代码示例可能需要调整,之前的例子使用了Kadane算法,可能需要解释清楚。 要注意引用之前的回答中的内容,比如在二维算法中提到的行预处理和列滑动,以及时间复杂度O(mn^2)。同时,用户可能对优化方法感兴趣,尤其是处理稀疏矩阵的情况,但这个问题可能留到相关问题中。 最后,生成的相关问题需要围绕二维滑动窗口的应用、优化、与其他算法对比等,比如与动态规划的区别,处理稀疏矩阵的优化,或者在图像处理中的具体应用。 需要确保回答准确,避免错误,比如二维滑动窗口的不同实现方式(固定窗口遍历或动态调整大小),以及典型应用场景。可能需要对比一维和二维的区别,但用户这次的问题集中在二维本身,所以重点放在二维部分。</think>### 二维滑动窗口算法详解 #### 定义 二维滑动窗口算法是**在二维矩阵中通过动态调整窗口边界或固定窗口尺寸,高效处理子矩阵问题**的扩展算法。其核心思想通过行/列方向的数据预处理与滑动机制,将二维问题降维到一维处理,典型应用包括子矩阵和计算、特征区域检测等[^2][^3]。 --- #### 核心原理 1. **预处理降维** 对矩阵进行行方向或列方向的前缀和计算,将二维矩阵压缩为多个一维数组。例如,计算每行的前缀和: $$ \text{row\_prefix}[i][j] = \sum_{k=0}^{j} \text{matrix}[i][k] $$ 这使得后续计算子矩阵和的时间复杂度从$O(hw)$降低到$O(1)$。 2. **窗口滑动方式** - **固定尺寸窗口**:遍历所有可能的$h \times w$窗口,直接计算区域特征(如图像滤波)。 - **动态调整窗口**:结合双指针技术,根据条件调整窗口大小或位置(如寻找最大子矩阵和)。 3. **时间复杂度** - 固定窗口遍历:$O(mn \cdot hw)$(需优化) - 动态调整窗口:通过降维处理可优化至$O(mn^2)$(如最大子矩阵和问题) --- #### 工作流程示例(最大子矩阵和) 1. **行方向预处理**:逐行计算前缀和数组。 2. **列方向滑动**:对每一组连续行(从第$i$行到第$j$行),将多行数据按列相加,得到一维数组。 3. **应用一维算法**:对生成的一维数组使用Kadane算法求最大子数组和[^3]。 ```python def maxSubMatrix(matrix): rows, cols = len(matrix), len(matrix[0]) max_sum = -float('inf') for top in range(rows): row_sum = [0] * cols for bottom in range(top, rows): # 按列累积行数据 for c in range(cols): row_sum[c] += matrix[bottom][c] # 一维Kadane算法 current_sum = row_sum[0] global_sum = row_sum[0] for num in row_sum[1:]: current_sum = max(num, current_sum + num) global_sum = max(global_sum, current_sum) max_sum = max(max_sum, global_sum) return max_sum ``` --- #### 应用场景 - **图像处理**:局部特征提取(如边缘检测滤波器)[^3] - **矩阵分析**:最大子矩阵和、满足条件的子矩阵计数 - **数据压缩**:分块编码中的窗口特征统计 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值