Cornfields
题意:给出一个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相关推荐
- poj--2019 Cornfields 2维RMQ
题目大意: 给定一个 N*N 的数组 求以(x1, y1) 为左上角 (x1 + b -1 ,y1 + b -1)为右下角 这个b*b的范围内最大值减最小值 看到最大值最小值当然想到RMQ啦 V ...
- 【POJ - 2019】Cornfields(二维st表,模板)
题干: FJ has decided to grow his own corn hybrid in order to help the cows make the best possible milk ...
- 【转】别人整理的DP大全
为什么80%的码农都做不了架构师?>>> 动态规划 动态规划 容易: 1018 , 1050 , 1083 , 1088 , 1125 , 1143 , 1157 , 1163 ...
- POJ2019(二维RMQ问题 ST)
题目:Cornfields 只是注意本题数据定义小一点,不然会超内存. #include <stdio.h> #include <iostream> #include < ...
- 杭电oj题目题型分类(转)
1001 整数求和 水题 1002 C语言实验题--两个数比较 水题 1003 1.2.3.4.5... 简单题 1004 渊子赛马 排序+贪心的方法归并 1005 Hero In Maze 广度搜索 ...
- HDOJ题目分类大全
版权声明:本文为博主原创文章,欢迎转载,转载请注明本文链接! https://blog.csdn.net/qq_38238041/article/details/78178043 杭电里面有很多题目, ...
- HDU题目分类大全【大集合】
基础题: 1000.1001.1004.1005.1008.1012.1013.1014.1017.1019.1021.1028.1029. 1032.1037.1040.1048.1056.105 ...
- python数学基础——单词统计
这个练习使用的是英文的单词统计,使用split通过单词中间的空格来做区分,在遍历的过程中通过对[字典]类型进行[字典推导式]的处理来计算每个单词出现的频次.但是由于过程中我们通过re的正则表达式来替换 ...
- POJ的题目分类(两个版本)
版本一: 简单题 1000A+B Problem 1001Exponentiation 1003 Hangover 1004 Financial Management 1005 I Think I N ...
最新文章
- spring问题--Unable to validate using XSD
- python拼图游戏_乐趣无穷的Python课堂
- 你会和丑且家境不好,但对你好的男孩结婚吗?
- es5如何实现promise_ES5实现Promise(1) - 事件循环机制
- Vue(八)发送跨域请求
- scala map,foreach,flatMap等方法对比
- linux hal 结构图
- 07.Thymeleaf使用与语法最全详解(精)
- windows7 安装docker
- 知途云仓2.0 淘宝礼品一件代发php源码
- 【数学建模】 插值算法
- 三相差分编码器转成脉冲信号或集电极开路转换模块
- echarts使用rich设置显示数据label颜色
- 人生之路 — 成长轨迹
- Linux--进程(一篇博客让你理解操作系统的底层)
- Flutter 导包错误 Target of URI doesn't exist
- nyist oj nyoj 865
- 推行国产操作系统的优劣
- php服务器内容修改时间,php设置服务器时间
- 虚拟机使用的是此版本 VMware Workstation 不支持的硬件版本。 模块“Upgrade”启动失败。 未能启动虚拟机。