类型:单调队列

传送门:>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. Class AtomicInteger

    Overview Package Class Use Tree Deprecated Index Help Java™ PlatformStandard Ed. 7 Prev Class Next C ...

  2. Spring集成Quarz开发环境搭建

    第一步,搭建Spring相关的环境,参照:http://www.cnblogs.com/dyh004/p/4645572.html 第二步,下载Quartz相关的压缩文件,解压,下载地址:http:/ ...

  3. Dapper-小型ORM之王(C#.NET)

    ORM:对象关系映射器,它直接将数据库映射到C#对象. 有很多ORM框架可用,Dapper是其中之一,被称为ORM之王. 下面是Dapper主要的一些功能: 速度快,性能好; 更少的代码行 对象映射 ...

  4. 最小的N个和(堆)

    描述: 有两个长度为N的序列 AB,从AB中各选一个数,可以得到N^2个和,求这N^2个和中最小的N个 输入 5 1 3 2 4 5 6 3 4 1 7 输出 2 3 4 4 5 分析: 首先限定输出 ...

  5. Python Revisited Day 01

    逻辑操作符 身份操作符 is a = ['AAA', 3, None] b = ['AAA', 3, None] a is b #False b = a a is b #True 身份比较速度快,原因 ...

  6. abaqus安装破解

    软件安装包 链接:http://pan.baidu.com/s/1pL4oxfX 密码:on1g 破解网页视频链接https://v.youku.com/v_show/id_XMTg4ODM5NjY5 ...

  7. os.path 下的各方法

    一.os.path os.path.abspath(file) #拿到当前程序(文件)的绝对目录. os.path.split(pathname) # 返回一个元组,第零个元素为文件上级绝对目录,第一 ...

  8. Centos下启动和关闭MySQL

    https://blog.csdn.net/gghh2015/article/details/78281585

  9. Column 'parent_id' specified twice

    Hibernate Column 'parent_id' specified twice问题解决--insertable = false, updatable = false的使用 - shendeg ...

  10. How to Configure Email Notification in Jenkins

    How to Configure Email Notification in Jenkins? - The Official 360logica Bloghttps://www.360logica.c ...