理想的正方形 bzoj-1047 HAOI-2007

题目大意:有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。

注释:$2\le a,b,n\le 10^3$,$n\le min(a,b)$。

想法:我的思路简直要死。通常的,我们优化暴力来完成对题目的求解。首先,想暴力。漂亮的暴力没想到,倒是想到一个a*b*n*n的,就是枚举每一个点,如果这个点可以作为n*n正方形的左上角,我就暴力枚举这个正方形的所有点。时间复杂度:O((a-n)*(b-n)*n*n)O(挖坑代填过不去)。想怎么优化:首先我们想,暴力的时候是连续的将n*n个数取最大值,我们可以怎么优化?我们可以对于每一行来讲维护一个窗口长度为n的单调队列来求出以每一个点结尾的前n个数的最值。然后我.. ....tm自以为是正解然后开始敲。自然T了之后还不知道怎么肥四,以为bz评测机又jb炸了。仔细分析了一下发现不太对。总的时间复杂度是a*b*n的,满的话是$10^9$的,不T才怪... ...想想再优化优化就好了嘛。对于求出来的矩阵,maxn[i][j]表示原矩阵以(i,j)为起点前n个数的最值。我们可以对maxn矩阵再维护一个窗口长度为n的单调队列,这样的话查询就是O(1)的了qwq.

最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define inf 2000000000
#define ll long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int a,b,n;
int v[1005][1005],mx[1005][1005],mn[1005][1005],t1[1005],t2[1005];
int val[1005],pos[1005];
void pre()
{
int l,r;
for(int i=1;i<=a;i++)
{
l=1,r=1;
for(int j=1;j<=b;j++)
{
while(l<r&&val[r-1]<=v[i][j])r--;
val[r]=v[i][j];pos[r]=j;r++;
if(pos[l]==j-n)l++;
if(j>=n)mx[i][j]=val[l];
}
l=1,r=1;
for(int j=1;j<=b;j++)
{
while(l<r&&val[r-1]>=v[i][j])r--;
val[r]=v[i][j];pos[r]=j;r++;
if(pos[l]==j-n)l++;
if(j>=n)mn[i][j]=val[l];
}
}
}
void solve()
{
int ans=inf;
int l,r;
for(int i=n;i<=b;i++)
{
l=1,r=1;
for(int j=1;j<=a;j++)
{
while(l<r&&val[r-1]>=mn[j][i])r--;
val[r]=mn[j][i];pos[r]=j;r++;
if(pos[l]==j-n)l++;
if(j>=n)t1[j]=val[l];
}
l=1,r=1;
for(int j=1;j<=a;j++)
{
while(l<r&&val[r-1]<=mx[j][i])r--;
val[r]=mx[j][i];pos[r]=j;r++;
if(pos[l]==j-n)l++;
if(j>=n)t2[j]=val[l];
}
for(int i=n;i<=a;i++)ans=min(ans,t2[i]-t1[i]);
}
printf("%d\n",ans);
}
int main()
{
a=read();b=read();n=read();
for(int i=1;i<=a;i++)
for(int j=1;j<=b;j++)
v[i][j]=read();
pre();
solve();
return 0;
}

小结:单调队列是优化dp的一种比较优秀的手段。而且好写好调,比什么单调栈强多了... ...

[bzoj1047][HAOI2007]理想的正方形_动态规划_单调队列的更多相关文章

  1. [luoguP2216] [HAOI2007]理想的正方形(二维单调队列)

    传送门 1.先弄个单调队列求出每一行的区间为n的最大值最小值. 2.然后再搞个单调队列求1所求出的结果的区间为n的最大值最小值 3.最后扫一遍就行 懒得画图,自己体会吧. ——代码 #include ...

  2. [luogu2216 HAOI2007] 理想的正方形 (2dST表 or 单调队列)

    题目描述 有一个ab的整数组成的矩阵,现请你从中找出一个nn的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: 第一行为3个整数,分别表示a,b,n的值 第二行至第a ...

  3. BZOJ1047: [HAOI2007]理想的正方形 [单调队列]

    1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2857  Solved: 1560[Submit][St ...

  4. bzoj千题计划215:bzoj1047: [HAOI2007]理想的正方形

    http://www.lydsy.com/JudgeOnline/problem.php?id=1047 先用单调队列求出每横着n个最大值 再在里面用单调队列求出每竖着n个的最大值 这样一个位置就代表 ...

  5. BZOJ1047[HAOI2007]理想的正方形——二维ST表

    题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非 ...

  6. BZOJ1047: [HAOI2007]理想的正方形

    传送门 蛤省省选果然水啊,我这种蒟蒻都能一遍A. 横向纵向维护两个单调队列,做两次求最大和最小的,总复杂度$O(NM)$ 码农题,考察代码实现能力 //BZOJ 1047 //by Cydiater ...

  7. [BZOJ1047][HAOI2007]理想的正方形(RMQ+DP)

    题意 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 思路 RMQ求 再DP 代码 #include<cstdio> #i ...

  8. 【单调队列】bzoj1047 [HAOI2007]理想的正方形

    先把整个矩阵处理成b[n][m-K+1].c[n][m-K+1]大小的两个矩阵,分别存储每行每K个数中的最大.最小值,然后再通过b.c处理出d.e分别表示K*K大小的子矩阵中的最大.最小值即可.单调队 ...

  9. [BZOJ1047][HAOI2007]理想的正方形 二维单调队列

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1047 我们对每矩阵的一列维护一个大小为$n$的单调队列,队中元素为矩阵中元素.然后扫描每一 ...

随机推荐

  1. easyui -tree的详细讲解

    代码的具体实现 @{    ViewBag.Title = "人员查找";    ViewBag.LeftWidth = "200px";    ViewBag ...

  2. JVM面试总结

    1.  Java虚拟机的内存布局(运行时数据区) 参考:https://www.cnblogs.com/lostyears/articles/8984171.html 2. GC算法及几种垃圾收集器 ...

  3. SPOJ 1811 SAM 初探

    思路: 一个串建SAM 另一个串在SAM上跑 //By SiriusRen #include <cstdio> #include <cstring> #include < ...

  4. [转]我是蒟蒻,但我有我的OI信仰

    我想最大的浪漫莫过于有人陪你征战OI吧 有多少无眠的夜晚?我总是在想, 到底是为了什么? 为了自招?为了省队?为了签约? 这条路很艰难,不可谓不凶险, 当你第一次踏上复试, 你肯定有看到过那些很厉害很 ...

  5. ACM_二维数组的查找

    二维数组的查找 Time Limit: 2000/1000ms (Java/Others) Problem Description: 给定一个n*m的二维数组,保证a[i][j] < a[i+1 ...

  6. 题解报告:hdu 1142 A Walk Through the Forest

    题目链接:acm.hdu.edu.cn/showproblem.php?pid=1142 Problem Description Jimmy experiences a lot of stress a ...

  7. yield让代码更加简洁

    不能传入out或ref public IEnumerable<Shop> GetShop() { ; i < ; i++) { yield return new Shop { ID ...

  8. DeadObjectException

    开发的过程中有时候会遇到DeadObjectException,说明系统service已经停止运行,解决的方式是在mainfistxml的application标签中添加android:hardwar ...

  9. Beta Edition [ Group 1 ]

    DeltaFish Beta Edition 一.七月开发过程 小组会议 DeltaFish 校园物资共享平台 第八次小组会议 GITHUB https://github.com/DeltaFishS ...

  10. 剔除重复jar包,查找重复类

    作为程序员,没有遇到过jar包冲突,不是你幸运,就是你还年轻. jar包冲突有着无穷的魔力,一提到就会有说不完的怨愤,道不清的忧伤,这都是内伤.jar 包冲突就像深藏地底的地雷,看上去平常无奇,一切是 ...