• 二维区间最值差


    一 问题描述

    约翰正在寻找最平坦的土地种植玉米,他花了很大的代价调查它的 N*N 公顷方形农场。每公顷都有一个整数高度,有 K 组查询。整数 B 是方形田地的一个边长。查询 B*B 子矩阵中最大高度和最小高度的差值。

    二 输入和输出

    1 输入

    第 1 行包含 3 个整数,N、B 和 K。第 2 到 N+1 行,每行都包含 N 个整数,代表 N*N 公顷每公顷的高度,每行的第 1 个整数都表示第 1 列,第 2 个整数都表示第 2 列。接下来的 K 行,每行都包含两个整数,分别表示查询子矩阵左上角和的行和列。

    2 输出

    对每个查询,都单行输出子矩阵中最大高度和最小高度的差值。

    三 输入和输出样例

    1 输入样例

    5 3 1

    5 1 2 6 3

    1 3 5 2 7

    7 2 4 6 1

    9 9 8 6 5

    0 6 9 3 9

    1 2

    2 输出样例

    5

    四 问题分析

    本问题属于二维区间最值查询问题,可以使用 ST 解决,只不过增加了一维,且查询时需要注意区间问题。Fmax[k][i][j] 表示第 k 行[i,i+2^j-1]区间的最大值,区间长度为 2^j。

    五 算法设计

    1 求出数据范围内所有数的 log 值,将其存储在 lb[] 中。

    2 将每个元素 a[k][k] 都存入 F[k][i][0] 中。

    3 创建二维 ST。

    4 从当前位置(x,y)开始,向右 B 列,向下 B 行,查询每一行的最大值和最小值,再求区间最大值和最小值。输出二维区间的最大值和最小值之差。

    六 代码

    1. package com.platform.modules.alg.alglib.poj2019;
    2. public class Poj2019 {
    3. public String output = "";
    4. private final int maxn = 260;
    5. int a[][] = new int[maxn][maxn];
    6. int lb[] = new int[maxn];
    7. int Fmax[][][] = new int[maxn][maxn][11];
    8. int Fmin[][][] = new int[maxn][maxn][11];
    9. // 求解所有 log 值,保存到数组 lb[]
    10. void Initlog() {
    11. lb[0] = -1;
    12. for (int i = 1; i < maxn; i++)
    13. lb[i] = (i & (i - 1)) > 0 ? lb[i - 1] : lb[i - 1] + 1;
    14. }
    15. void ST(int n) {
    16. for (int k = 1; k <= n; k++) // 多一维
    17. for (int i = 1; i <= n; i++)
    18. Fmax[k][i][0] = Fmin[k][i][0] = a[k][i];
    19. for (int k = 1; k <= n; k++)
    20. for (int j = 1; j <= lb[n]; j++)
    21. for (int i = 1; i + (1 << j) - 1 <= n; i++) {
    22. Fmax[k][i][j] = Math.max(Fmax[k][i][j - 1], Fmax[k][i + (1 << (j - 1))][j - 1]);
    23. Fmin[k][i][j] = Math.min(Fmin[k][i][j - 1], Fmin[k][i + (1 << (j - 1))][j - 1]);
    24. }
    25. }
    26. // 从坐标为(x,y)的地方开始,右下扩展 B 长度
    27. void solve(int x, int y, int B) {
    28. int k = lb[B];
    29. int maxx = -1;
    30. int minx = 0x3f3f3f3f;
    31. int l = y, r = y + B - 1;
    32. for (int i = x; i < x + B; i++) { // 查询每一行的最值
    33. maxx = Math.max(maxx, Math.max(Fmax[i][l][k], Fmax[i][r - (1 << k) + 1][k]));
    34. minx = Math.min(minx, Math.min(Fmin[i][l][k], Fmin[i][r - (1 << k) + 1][k]));
    35. }
    36. output += (maxx - minx) + "\n";
    37. }
    38. public String cal(String input) {
    39. int N, B, K;
    40. int x, y; // 每次查询的坐标
    41. Initlog();
    42. String[] line = input.split("\n");
    43. String[] words = line[0].split(" ");
    44. N = Integer.parseInt(words[0]);
    45. B = Integer.parseInt(words[1]);
    46. K = Integer.parseInt(words[2]);
    47. for (int i = 1; i <= N; i++){
    48. String[] nums = line[i].split(" ");
    49. for (int j = 1; j <= N; j++){
    50. a[i][j] = Integer.parseInt(nums[j-1]);
    51. }
    52. }
    53. ST(N);
    54. for (int i = 0; i < K; i++) {
    55. String[] query = line[1 + N+i].split(" ");
    56. x = Integer.parseInt(query[0]);
    57. y = Integer.parseInt(query[1]);
    58. solve(x, y, B);
    59. }
    60. return output;
    61. }
    62. }

    七 测试

     

  • 相关阅读:
    C++ Qt开发:QNetworkAccessManager网络接口组件
    猿创征文|深聊MySQL,从入门到入坟之:应该是全网最详细的MySQL知识点汇总,必须收藏。
    Linux Ftrace介绍
    readhat8搭建SFTP双机高可用并配置Rsync数据实时同步
    enter ubuntu boot option in virt-manager
    springboot mybatis多数据源配置
    java注解和通过反射获取注解值
    08【子查询】
    Golang封装一个request类支持socks和http代理
    【工程应用九】再谈基于离散夹角余弦相似度指标的形状匹配优化(十六角度量化+指令集加速+目标只有部分在图像内的识别+最小外接矩形识别重叠等)
  • 原文地址:https://blog.csdn.net/chengqiuming/article/details/126669026