【BZOJ】【1047】【HAOI2007】理想的正方形
DP/单调队列优化
一眼看上去就是DP
我想的naive的二维DP是酱紫滴:
mx[i][j][k]表示以(i,j)为右下角的k*k的正方形区域内的最大值,mn[i][j][k]同理
mx[i][j][k]=max(v[i][j],max(v[i-k+1][j-k+1],max(mx[i-1][j][k-1],mx[i][j-1][k-1]))),mn[i][j][k]同理
这个DP是既爆空间又爆时间的……我把空间优化了一下:由于转移的时候只用到了i-1行的DP值,所以可以用滚动数组。
但是时间上我优化不来了……
//BZOJ 1047
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
inline int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=,M=,INF=~0u>>;
typedef long long LL;
/******************tamplate*********************/
int a,b,n,ans=INF;
int mx[][N][M],mn[][N][M],v[N][N];
int main(){
#ifndef ONLINE_JUDGE
freopen("1047.in","r",stdin);
freopen("1047.out","w",stdout);
#endif
a=getint(); b=getint(); n=getint();
F(i,,a) F(j,,b) v[i][j]=getint();
F(i,,a){
int now=i&;
F(j,,b){
mx[now][j][]=mn[now][j][]=v[i][j];
F(k,,min(n,min(i,j))){
mx[now][j][k]=max(v[i][j],max(v[i-k+][j-k+],max(mx[now][j-][k-],mx[now^][j][k-])));
mn[now][j][k]=min(v[i][j],min(v[i-k+][j-k+],min(mn[now][j-][k-],mn[now^][j][k-])));
}
if (min(i,j)>=n) ans=min(ans,mx[now][j][n]-mn[now][j][n]);
}
}
printf("%d\n",ans);
return ;
}
(80分TLE)
看了下题解:单调队列!
豁然开朗,这不就是一个二维的滑动窗口吗?我个sb没想到啊……
每行先做一遍单调队列优化DP,求出mx[i][j]表示以(i,j)为右端点的横着的n个格子的最大值(mn[i][j]同理)
然后再对每列做一遍……(这时候每一格的值就代表了横着的n个格子的最优值)
在对列进行DP的时候,为了节省(tou)空间(lan)我做完一列的DP就更新了一下答案……
P.S.感觉这个做法就是把一个二维的DP拆成(n+n)个一维DP分别搞……因为一维DP好搞、好优化= =所以总体上复杂度是降低了……(二维是n*n个状态,k的转移,一维是n个状态,转移可以优化到O(1),所以虽然一维DP要做2n遍,但总复杂度是$2×n^2$,更优)
/**************************************************************
Problem: 1047
User: Tunix
Language: C++
Result: Accepted
Time:1980 ms
Memory:13240 kb
****************************************************************/ //BZOJ 1047
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
inline int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=,M=,INF=~0u>>;
typedef long long LL;
/******************tamplate*********************/
int a,b,n,ans=INF;
int mx[N][N],mn[N][N],Q[N],t1[N],t2[N],v[N][N];
void get_row(){
int l=,r=-;
F(i,,a){
l=,r=-;
F(j,,b){
while(l<=r && v[i][Q[r]]<=v[i][j])r--;
Q[++r]=j;
while(l<=r && j-Q[l]>=n) l++;
if (j>=n) mx[i][j]=v[i][Q[l]];
}
l=,r=-;
F(j,,b){
while(l<=r && v[i][Q[r]]>=v[i][j])r--;
Q[++r]=j;
while(l<=r && j-Q[l]>=n) l++;
if (j>=n) mn[i][j]=v[i][Q[l]];
}
}
}
void get_line(){
int l,r;
F(j,n,b){
l=,r=-;
F(i,,a){
while(l<=r && mx[Q[r]][j]<=mx[i][j]) r--;
Q[++r]=i;
while(l<=r && i-Q[l]>=n) l++;
if (i>=n) t1[i]=mx[Q[l]][j];
}
l=,r=-;
F(i,,a){
while(l<=r && mn[Q[r]][j]>=mn[i][j]) r--;
Q[++r]=i;
while(l<=r && i-Q[l]>=n) l++;
if (i>=n) t2[i]=mn[Q[l]][j];
}
F(i,n,a) ans=min(ans,t1[i]-t2[i]);
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1047.in","r",stdin);
freopen("1047.out","w",stdout);
#endif
a=getint(); b=getint(); n=getint();
F(i,,a) F(j,,b) v[i][j]=getint();
get_row();
get_line();
printf("%d\n",ans);
return ;
}
(正解)
【BZOJ】【1047】【HAOI2007】理想的正方形的更多相关文章
- bzoj 1047 : [HAOI2007]理想的正方形 单调队列dp
题目链接 1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2369 Solved: 1266[Submi ...
- BZOJ 1047: [HAOI2007]理想的正方形( 单调队列 )
单调队列..先对每一行扫一次维护以每个点(x, y)为结尾的长度为n的最大最小值.然后再对每一列扫一次, 在之前的基础上维护(x, y)为结尾的长度为n的最大最小值. 时间复杂度O(ab) (话说还是 ...
- [BZOJ 1047] [HAOI2007] 理想的正方形 【单调队列】
题目链接:BZOJ - 1047 题目分析 使用单调队列在 O(n^2) 的时间内求出每个 n * n 正方形的最大值,最小值.然后就可以直接统计答案了. 横向有 a 个单调队列(代码中是 Q[1] ...
- BZOJ 1047: [HAOI2007]理想的正方形
题目 单调队列是个很神奇的东西,我以前在博客写过(吧) 我很佩服rank里那些排前几的大神,700ms做了时限10s的题,简直不能忍.(但是我还是不会写 我大概一年半没写单调队列,也有可能根本没有写过 ...
- BZOJ 1047: [HAOI2007]理想的正方形 单调队列瞎搞
题意很简明吧? 枚举的矩形下边界和右端点即右下角,来确定矩形位置: 每一个纵列开一个单调队列,记录从 i-n+1 行到 i 行每列的最大值和最小值,矩形下边界向下推移的时候维护一下: 然后在记录的每一 ...
- bzoj 1047: [HAOI2007]理想的正方形【单调队列】
没有复杂结构甚至不长但是写起来就很想死的代码类型 原理非常简单,就是用先用单调队列处理出mn1[i][j]表示i行的j到j+k-1列的最小值,mx1[i][j]表示i行的j到j+k-1列的最大值 然后 ...
- [bzoj 1047][HAOI2007]理想正方形(单调队列)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1047 分析: 第一感觉二维线段树当然没问题但是挺慢的. 注意到要求的正方形形中的最大最小边长是 ...
- 1047: [HAOI2007]理想的正方形 - BZOJ
Description 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小.Input 第一行为3个整数,分别表示a,b,n的值第二行至第a ...
- 【BZOJ】1047: [HAOI2007]理想的正方形(单调队列/~二维rmq+树状数组套树状数组)
http://www.lydsy.com/JudgeOnline/problem.php?id=1047 树状数组套树状数组真心没用QAQ....首先它不能修改..而不修改的可以用单调队列做掉,而且更 ...
- 【单调队列】bzoj 1407 [HAOI2007]理想的正方形
[题意] 给定一个n*m的矩阵,求所有大小为k*k的正方形中(最大值-最小值)的最小值 [思路] 先横着算出每一行的长度为k的窗口内的最大值,变成一个n*(m-k+1)的矩阵mx 再竖着算出每一列的长 ...
随机推荐
- K-Means(K均值)算法
昨晚在脑内推导了一晚上的概率公式,没推导出来,今早师姐三言两语说用K-Means解决,太桑心了,昨晚一晚上没睡好. 小笨鸟要努力啊,K-Means,最简单的聚类算法,好好实现一下. 思路: 共有M个样 ...
- 利用脚本修改SQL SERVER排序规则
利用脚本修改SQL SERVER排序规则 编写人:CC阿爸 2014-3-1 l 今年的一项重要工作是对公司所用系统进行繁简的转换,程序转成简体基本很容易解决,但数据库转换成简体,就没那么容易了.经 ...
- silverlight获取web的url参数
1.网址(如:http://localhost:8081/index.aspx?name=123) 2.获取name=123的信息 3.IDictionary<string,string> ...
- Linux安全运维日志排查几个 tips
运维日志排查记录 前言 记录一些排查常见日志的命令,方法wiki,欢迎补充(Markdown 语法). 常用命令 查找关键词并统计行数 cat 2015_7_25_test_access.log | ...
- delphi的多线程编程
多线程的基本概念 win 98/nt/2000/xp 是个多任务操作系统,也就是:一个进程可以划分为多个线程,每个线程轮流占用cpu 运行时间和资源,或者说,把cpu 时间划成片,每个片分给不同的线程 ...
- DataTable使用总结
1.DataTable数据去重 static void Main(string[] args) { DataTable dt = new DataTable();//创建表 DataColumn dc ...
- 学习simple.data之进阶篇
一.结果排序 -OrderBy(升序) -OrderByDescending(降序) db.Product.All().OrderByFactoryName(); db.Product.All().O ...
- SublimeText插件Emmet的自定义模板
在前端界,作为快速生成代码的Emmet插件相当给力.最近在学bootstrap,需要频繁生成html头文件,我就想着自定义模板.国内只有基础教程,只好自己读英文文档了. Emmet国内基础教程地址: ...
- Oracle 11g Windows 迁移至 Linux
OS: windows server 2008 R2 enterprise DB: 11.2.0.1.0 数据库配置: ORACLE_BASE=D:\app\Administrator ORACLE_ ...
- AppCan认为,移动APP开发不是技术活
很多粉丝反应,AppCan的文章太专业了,技术大大们毫不费劲,小白看的晕乎乎. 时代变了,5年前,AppCan的受众只有开发者.现在,政府高管.集团董事长.非技术类管理者.中小企业主.各行各业的管理者 ...