类型:单调队列

传送门:>Here<

题意:给出一个$M*N$的矩阵,每一个代表这一格土地的肥沃程度。现在要求修建一个$C*D$的矩形花坛,矩形绿化带的面积为$A*B$,要求花坛被包裹在绿化带中,且不能碰到绿化带边缘。问绿化带的最大肥沃程度

解题思路

暴力做法:枚举绿化带,然后选出能使其肥沃程度最大的花坛位置。

很容易发现要使绿化带的肥沃程度最大,也就是让所选的花坛的肥沃程度尽量小。由此,问题转化为了求固定矩形内部规定大小的最小子矩形

为了表达方便,以下称绿化带为矩形$AB$,花坛为矩形$CD$。

为了计算方便,我们可以先预处理出以$(i,j)$为右下角的矩形$AB$和矩形$CD$的肥沃程度。利用前缀和处理即可

显然固定矩形$AB$以后,矩形$CD$的可取范围也被固定了。这个范围是可以计算的。设矩形$AB$的右下角为$(i+1,j+1)$,则矩形$CD$的右下角可取范围是$(i+1-(A-1)+C \rightarrow i, j+1-(B-1)+D \rightarrow j)$。也就是$$(i-A+C+2 \rightarrow i, j-B+D+2 \rightarrow j)$$由于我们已经计算出了以$(i,j)$为右下角的矩形$CD$的肥沃程度,因此我们可以把每一个格子看做是一个矩形$CD$。于是要求以同一个$i$作为右下角横坐标的矩形时,他们就是一个横行里的格子。用一个单调队列就很容易求出

求出范围内每一个横行的最小值以后,对所有这些最小值再竖着用单调队列求一个最小值。即可以得出整个范围内的最小值。问题就解决了

这题的代码实现也很难(本蒟蒻打了2.5h+),由于边界条件如此的坑而且样例又如此的水,不得不自己造了好几组数据一个一个调……关键在于把控清楚每一个数组表示的具体内容,包括要不要$+1或-1$

Code

/*By DennyQi 2018.8.19*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define r read()
#define Max(a,b) (((a)>(b)) ? (a) : (b))
#define Min(a,b) (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
const int MAXN = ;
const int INF = ;
inline int read(){
int x = ; int w = ; register int c = getchar();
while(c ^ '-' && (c < '' || c > '')) c = getchar();
if(c == '-') w = -, c = getchar();
while(c >= '' && c <= '') x = (x<<) + (x<<) + c - '', c = getchar();
return x * w;
}
int M,N,A,B,C,D,h,t;
int a[MAXN][MAXN],sum[MAXN][MAXN],ab[MAXN][MAXN],cd[MAXN][MAXN];
int q[MAXN],mcd[MAXN][MAXN],mx[MAXN][MAXN];
int main(){
N = r, M = r;
A = r, B = r, C = r, D = r;
for(int i = ; i <= N; ++i){
h = , t = ;
for(int j = ; j <= M; ++j){
a[i][j] = r;
sum[i][j] = sum[i-][j] + sum[i][j-] - sum[i-][j-] + a[i][j];
ab[i][j] = sum[i][j] - sum[i][j-B] - sum[i-A][j] + sum[i-A][j-B];
cd[i][j] = sum[i][j] - sum[i][j-D] - sum[i-C][j] + sum[i-C][j-D];
if(i > C && j > D && i < N && j < M){
while(h <= t && cd[i][q[t]] >= cd[i][j]) --t;
q[++t] = j;
if(j - B + D + > ){
while(h <= t && q[h] < j - B + D + ) ++h;
}
if(i > C && j > D) mcd[i][j] = cd[i][q[h]];
}
}
}
for(int k = B; k <= M; ++k){
h = , t = ;
q[] = ;
for(int i = C+; i <= N; ++i){
while(h <= t && q[h] < i - A + C + ) ++h;
if(i >= A) mx[i][k] = mcd[q[h]][k-];
while(h <= t && mcd[q[t]][k-] >= mcd[i][k-]) --t;
q[++t] = i;
}
}
int ans = ;
for(int i = A; i <= N; ++i){
for(int j = B; j <= M; ++j){
ans = Max(ans, ab[i][j] - mx[i][j]);
}
}
printf("%d", ans);
return ;
}

[HAOI2007] 修筑绿化带的更多相关文章

  1. P2219 [HAOI2007]修筑绿化带(单调队列)

    P2219 [HAOI2007]修筑绿化带 二维单调队列 写了这题 P2216 [HAOI2007]理想的正方形  后,你发现可以搞个二维单调队列 来保存矩形(i+1,i+A-1)(j+1,j+B-1 ...

  2. 洛谷2219:[HAOI2007]修筑绿化带——题解

    https://www.luogu.org/problemnew/show/P2219#sub 为了增添公园的景致,现在需要在公园中修筑一个花坛,同时在画坛四周修建一片绿化带,让花坛被绿化带围起来. ...

  3. luogu2219 [HAOI2007]修筑绿化带

    和「理想的正方形」比较相似,需要先掌握那道题. 花坛外头每一边必须套上绿化带 #include <iostream> #include <cstdio> using names ...

  4. [luoguP2219] [HAOI2007]修筑绿化带(单调队列)

    传送门 需要n*m的算法,考虑单调队列 可以预处理出来 a[i][j]表示以i,j为右下角的绿化带+花坛的和 b[i][j]表示以i,j为右下角的花坛的和 那么我们可以单调队列跑出来在A-C-1,B- ...

  5. 洛谷.2219.[HAOI2007]修筑绿化带(单调队列)

    题目链接 洛谷 COGS.24 对于大的矩阵可以枚举:对于小的矩阵,需要在满足条件的区域求一个矩形和的最小值 预处理S2[i][j]表示以(i,j)为右下角的C\(*\)D的矩阵和, 然后对于求矩形区 ...

  6. P2219 [HAOI2007]修筑绿化带

    我是题面 这道题跟理想的正方形很像,不大明白蛤OI是怎么想的,一年出两道这么相近的题 这道题有两个矩形,所以就有了两种做法(说是两种做法,其实只是维护的矩形不同) 一种是维护大矩形,一种是维护小矩形, ...

  7. 洛谷P2219 [HAOI2007]修筑绿化带(单调队列)

    传送门 啧……明明以前做到过这种类型的题结果全忘了…… 这种矩阵的,一般都是先枚举行,然后对列进行一遍单调队列,搞出右下角在每一行中合法位置时的最小权值 再枚举列,对行做一遍单调队列,用之前搞出来的最 ...

  8. luogu 2219[HAOI2007]修筑绿化带 单调队列

    Code: #include<bits/stdc++.h> using namespace std; #define setIO(s) freopen(s".in",& ...

  9. [HAOI2007]修筑绿化带 题解

    题意分析 给出一个 $m*n$ 的矩阵 $A$ ,要求从中选出一个 $a*b$ 的矩阵 $B$ ,再从矩阵 $B$ 中选出一个 $c*d$ 的矩阵 $C$ ,要求矩阵 $B,C$ 的边界不能重合,求矩 ...

随机推荐

  1. flask登录插件 flask-login

    Flask-Login为Flask提供了用户会话管理,它处理了日常的登入登出且长时间记住用户的会话 使用: 1.配置,初始化 LoginManager 创建实例 loginManger = Login ...

  2. H5 14-后代选择器和子元素选择器

    14-后代选择器和子元素选择器 <!DOCTYPE html> <html lang="en"> <head> <meta charset ...

  3. PAT L2-014 列车调度

    https://pintia.cn/problem-sets/994805046380707840/problems/994805063166312448 火车站的列车调度铁轨的结构如下图所示. 两端 ...

  4. python3 常见的两种文件上传方法

    1.上传页面带input type格式send_keys传值方式上传不能大于60k(具体看开发设置的value)文件大小 fx.find_element_by_id('xx').send_keys(r ...

  5. 手机移动端input date placehoder不显示

    要解决这个问题,我们可以伪造一个placehoder,通过css跟js来解决这个问题. 为什么要用js的原因是因为当你选择了时间之后,placehoder的文字没有清除掉,所以我们就需要把这个伪造的p ...

  6. linux重装后配一些库

    #先要设置软件源 sudo apt-get update sudo apt-get upgrade #播放器 sudo apt-get install smplayer qt sudo apt-get ...

  7. laravel 项目表单中有csrf_token,但一直报错419错误 解决redis连接错误:MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persi

    laravel 项目表单中有csrf_token,但一直报错419错误,因为项目中使用到Redis缓存,在强制关闭Redis后出现的问题,查询laravel.log文件查找相关问题 安装redis后在 ...

  8. day 7-16 单表查询

    一.准备工作 先把表建立好,方便一会查询. create table emp( id int not null unique auto_increment, name varchar(20) not ...

  9. MyBatis映射文件1(增删改、insert获取自增主键值)

    增删改 Mybatis为我们提供了<insert>.<update>.<delete>标签来对应增删改操作 在接口中写增删改的抽象方法 void addEmp(Em ...

  10. hadoop的缺点

    Hadoop的限制 Hadoop只能执行批量处理,并且只以顺序方式访问数据.这意味着必须搜索整个数据集,即使是最简单的搜索工作.