题意:给出一个n阶的方阵,给你一个点,求以这个点为左上角的b*b方阵的最大值和最小值的差值。

三种做法,第一种在求解的过程中记录答案(这应该是叫做记忆化),一种方法是二维RMQ,还有优先队列。

1s内可进行的运算次数约为1e8,记忆化枚举最坏的情况下耗时约为2.5e8,如果数据弱一些就可以划过去了,然后这题还真的过了

#include<cstdio>
int n,b,k,i,j,x,y,maxm,minm,arr[300][300],ans[300][300];
int main(){scanf("%d%d%d",&n,&b,&k);for(i=1;i<=n;i++)for(j=1;j<=n;j++)scanf("%d",&arr[i][j]);while(k--){scanf("%d%d",&x,&y);if(!ans[x][y]){maxm=0;minm=0x3f3f3f3f;for(i=1;i<=b;i++)for(j=1;j<=b;j++){if(arr[i+x-1][j+y-1]<minm)minm=arr[i+x-1][j+y-1];if(arr[i+x-1][j+y-1]>maxm)maxm=arr[i+x-1][j+y-1];}ans[x][y]=maxm-minm;}printf("%d\n",ans[x][y]);}return 0;
}

RMQ模板:(这方法不知道为什么我WA了,所以代码仅供参考qaq)
一维RMQ求得是区间区间的最值,用一个二维数组dq[i][k]来表示以i为左端点的连续2k个数字,即右端点为i+2k-1.则可以将其拆分成两个区间,(i,2k-1-1)和(ik-1,i+2k-1),原区间最大值为这两个区间的最大值,拆分后的区间又可以不断地拆分,直到长度为1
一维RMQ实现

for(int j=1;1<<j<=k;j++){for(int i=1;i+(1<<j)-1<=k;i++){dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);}}

二维RMQ只是在一维RMQ增加了一位,所以我们用四维数组dp[i][j][k][l]表示以(i,j)为左上角,(i+2k-1,j+2l-1)为右下角的矩阵,和一维RMQ一样,可以将大的矩阵拆分为小的矩阵,不断求出其最大值,直到矩阵为1*1方阵

//这个大家看看就好,我也是做题的时候学的二维RMQ,可能有问题,虽然过了自己的例子,但总归没用这个AC,
for (int j = 0; (1 << j) <=n; j++) {for (int l = 0; (1<<l) <= n; l++) {if (l == 0 && j == 0) continue;for (int row = 1; row + (1 << j) - 1 <= n; row++) {for (int col = 1; col + (1 << l) - 1 <= n; col++) {if (j==0) {//当有一维的长度为1是就是一个一维RMQmax_rix[row][col][j][l] = max(max_rix[row][col + (1 << (l - 1))][j][l - 1], max_rix[row][col][j][l - 1]);min_rix[row][col][j][l] = min(min_rix[row][col + (1 << (l - 1))][j][l - 1], min_rix[row][col][j][l - 1]);}else{max_rix[row][col][j][l] = max(max_rix[row + (1 << (j - 1))][col][j - 1][l], max_rix[row][col][j - 1][l]);min_rix[row][col][j][l] = min(min_rix[row + (1 << (j - 1))][col][j - 1][l], min_rix[row][col][j - 1][l]);}}}}}

最后是优先队列,用两个单调队列预处理,求出各个b*b矩阵的最大值和最小值,然后询问时直接使用即可,灵感来源与一道求子矩阵最大值和的题
题目链接
我的题解链接
AC代码

#include<cstdio>
#include<deque>using namespace std;int qmax[270][270], qmin[270][270], arr[270][270], ansmax[270][270],ansmin[270][270];struct node {int id;int val;
};int main() {int n, b, k;scanf("%d %d %d", &n, &b, &k);for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {scanf("%d", &arr[i][j]);}}for (int i = 1; i <= n; i++) {deque<node> dqmax, dqmin;for (int j = 1; j <= n; j++) {while (!dqmax.empty() && arr[i][j] > dqmax.back().val) dqmax.pop_back();while (!dqmin.empty() && arr[i][j] < dqmin.back().val) dqmin.pop_back();while (!dqmax.empty() && j - dqmax.front().id >= b) dqmax.pop_front();while (!dqmin.empty() && j - dqmin.front().id >= b) dqmin.pop_front();dqmax.push_back({j,arr[i][j]});dqmin.push_back({j,arr[i][j]});if (j >= b) {ansmax[i][j - b + 1] = dqmax.front().val;ansmin[i][j - b + 1] = dqmin.front().val;}}}/*printf("\n");for (int i = 1; i <= n; i++) {for (int j = 1; j+b-1 <= n; j++) {printf("%d ", ansmax[i][j]);}printf("\n");}printf("\n");*/for (int i = 1; i <= n; i++) {deque<node> dqmax, dqmin;for (int j = 1; j <= n; j++) {int ma = ansmax[j][i], mi = ansmin[j][i];while (!dqmax.empty() && ma > dqmax.back().val) dqmax.pop_back();while (!dqmin.empty() && mi < dqmin.back().val) dqmin.pop_back();while (!dqmax.empty() && j - dqmax.front().id >= b) dqmax.pop_front();while (!dqmin.empty() && j - dqmin.front().id >= b) dqmin.pop_front();dqmax.push_back({j,ma});dqmin.push_back({j,mi});if (j >= b) {ansmax[j-b+1][i] = dqmax.front().val;ansmin[j-b+1][i] = dqmin.front().val;}}}/*printf("\n");for (int i = 1; i+b-1 <= n; i++) {for (int j = 1; j + b - 1 <= n; j++) {printf("%d ", ansmax[i][j]);}printf("\n");}printf("\n");*/while (k--) {int l, r;scanf("%d %d", &l, &r);printf("%d\n", ansmax[l][r] - ansmin[l][r]);}
}

Cornfields相关推荐

  1. poj--2019 Cornfields 2维RMQ

    题目大意: 给定一个 N*N 的数组   求以(x1, y1) 为左上角  (x1 + b -1 ,y1 + b -1)为右下角 这个b*b的范围内最大值减最小值 看到最大值最小值当然想到RMQ啦 V ...

  2. 【POJ - 2019】Cornfields(二维st表,模板)

    题干: FJ has decided to grow his own corn hybrid in order to help the cows make the best possible milk ...

  3. 【转】别人整理的DP大全

    为什么80%的码农都做不了架构师?>>>    动态规划 动态规划 容易: 1018 , 1050 , 1083 , 1088 , 1125 , 1143 , 1157 , 1163 ...

  4. POJ2019(二维RMQ问题 ST)

    题目:Cornfields 只是注意本题数据定义小一点,不然会超内存. #include <stdio.h> #include <iostream> #include < ...

  5. 杭电oj题目题型分类(转)

    1001 整数求和 水题 1002 C语言实验题--两个数比较 水题 1003 1.2.3.4.5... 简单题 1004 渊子赛马 排序+贪心的方法归并 1005 Hero In Maze 广度搜索 ...

  6. HDOJ题目分类大全

    版权声明:本文为博主原创文章,欢迎转载,转载请注明本文链接! https://blog.csdn.net/qq_38238041/article/details/78178043 杭电里面有很多题目, ...

  7. HDU题目分类大全【大集合】

    基础题: 1000.1001.1004.1005.1008.1012.1013.1014.1017.1019.1021.1028.1029.  1032.1037.1040.1048.1056.105 ...

  8. python数学基础——单词统计

    这个练习使用的是英文的单词统计,使用split通过单词中间的空格来做区分,在遍历的过程中通过对[字典]类型进行[字典推导式]的处理来计算每个单词出现的频次.但是由于过程中我们通过re的正则表达式来替换 ...

  9. POJ的题目分类(两个版本)

    版本一: 简单题 1000A+B Problem 1001Exponentiation 1003 Hangover 1004 Financial Management 1005 I Think I N ...

最新文章

  1. spring问题--Unable to validate using XSD
  2. python拼图游戏_乐趣无穷的Python课堂
  3. 你会和丑且家境不好,但对你好的男孩结婚吗?
  4. es5如何实现promise_ES5实现Promise(1) - 事件循环机制
  5. Vue(八)发送跨域请求
  6. scala map,foreach,flatMap等方法对比
  7. linux hal 结构图
  8. 07.Thymeleaf使用与语法最全详解(精)
  9. windows7 安装docker
  10. 知途云仓2.0 淘宝礼品一件代发php源码
  11. 【数学建模】 插值算法
  12. 三相差分编码器转成脉冲信号或集电极开路转换模块
  13. echarts使用rich设置显示数据label颜色
  14. 人生之路 — 成长轨迹
  15. Linux--进程(一篇博客让你理解操作系统的底层)
  16. Flutter 导包错误 Target of URI doesn't exist
  17. nyist oj nyoj 865
  18. 推行国产操作系统的优劣
  19. php服务器内容修改时间,php设置服务器时间
  20. 虚拟机使用的是此版本 VMware Workstation 不支持的硬件版本。 模块“Upgrade”启动失败。 未能启动虚拟机。

热门文章

  1. PostgreSQL备份恢复之pgbackRest恢复
  2. C语言基本变量语法输出和输入方法
  3. 计算机网络 一、 IP地址,域名,DNS
  4. 传统企业如何电子商务
  5. ffmpeg 收集 (刚开始,有待完善)
  6. 小程序banner广告和激励广告
  7. 3个窗口卖票java_三个窗口同时卖火车票,如何用代码将该场景实现?
  8. R在GIS中用ggmap地理空间数据分析
  9. 全方位解读企业微信和个人微信的区别
  10. java 代码块(静态代码块、局部代码块、构造代码块)