Description

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

第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。
Output

仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。
Sample Input
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
Sample Output
1
问题规模
(1)矩阵中的所有数都不超过1,000,000,000
(2)20%的数据2<=a,b<=100,n<=a,n<=b,n<=10
(3)100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100

看了题解,过了好几天又看这道题,感慨万分,好久不做RMQ果然什么都忘了

就是先做一遍右边的,把右边n格的最大值最小值存到最左边这一格

然后做一遍向下的,把下面n格的最值存到这一格,现在,每一个n*n的正方形的信息都存到左上角了,扫一遍就行了

 const
maxn=;
var
a,b:array[..maxn,..maxn]of longint;
n,m,k:longint; procedure down(var x:longint;y:longint);
begin
if x>y then x:=y;
end; procedure up(var x,y:longint);
begin
if x<y then x:=y;
end; procedure main;
var
i,j,l,s,ans:longint;
begin
read(n,m,k);
for i:= to n do
for j:= to m do
begin
read(a[i,j]);
b[i,j]:=a[i,j];
end;
l:=;
while l<k do
begin
for i:= to n do
for j:= to m do
begin
s:=j+l;
down(s,m-l+);
down(s,j+k-l);
up(a[i,j],a[i,s]);
down(b[i,j],b[i,s]);
end;
l:=l<<;
end;
l:=;
while l<k do
begin
for i:= to n do
for j:= to m do
begin
s:=i+l;
down(s,n-l+);
down(s,i+k-l);
up(a[i,j],a[s,j]);
down(b[i,j],b[s,j]);
end;
l:=l<<;
end;
ans:=maxlongint;
for i:= to n-k+ do
for j:= to m-k+ do
down(ans,a[i,j]-b[i,j]);
write(ans);
end; begin
main;
end.

结果写完就被鄙视了,z55250825 ORZ,其实可以用单调队列

 const
maxn=;
var
a,b:array[..maxn,..maxn]of longint;
n,m,k,ans:longint; function min(x,y:longint):longint;
begin
if x<y then exit(x);
exit(y);
end; procedure init;
var
i,j:longint;
begin
read(n,m,k);
for i:= to n do
for j:= to m do
begin
read(a[i,j]);
b[i,j]:=a[i,j];
end;
end; var
q:array[..maxn,..]of longint;
head,tail:longint; procedure work;
var
i,j:longint;
begin
for i:= to n do
begin
head:=;
tail:=;
for j:= to m do
begin
while (tail>=head) and (q[tail,]<=a[i,j]) do
dec(tail);
inc(tail);
q[tail,]:=j;
q[tail,]:=a[i,j];
while q[head,]<=j-k do
inc(head);
a[i,j]:=q[head,];
end;
end;
for j:= to m do
begin
head:=;
tail:=;
for i:= to n do
begin
while (tail>=head) and (q[tail,]<=a[i,j]) do
dec(tail);
inc(tail);
q[tail,]:=i;
q[tail,]:=a[i,j];
while q[head,]<=i-k do
inc(head);
a[i,j]:=q[head,];
end;
end;
for i:= to n do
begin
head:=;
tail:=;
for j:= to m do
begin
while (tail>=head) and (q[tail,]>=b[i,j]) do
dec(tail);
inc(tail);
q[tail,]:=j;
q[tail,]:=b[i,j];
while q[head,]<=j-k do
inc(head);
b[i,j]:=q[head,];
end;
end;
for j:= to m do
begin
head:=;
tail:=;
for i:= to n do
begin
while (tail>=head) and (q[tail,]>=b[i,j]) do
dec(tail);
inc(tail);
q[tail,]:=i;
q[tail,]:=b[i,j];
while q[head,]<=i-k do
inc(head);
b[i,j]:=q[head,];
end;
end;
ans:=maxlongint;
for i:=k to n do
for j:=k to m do
ans:=min(ans,a[i,j]-b[i,j]);
write(ans);
end; begin
init;
work;
end.

Wikioi上实在是过不了,然后写了一个C++的

 #include<cstdio>
using namespace std; const int maxn=; int a[maxn][maxn],b[maxn][maxn],n,m,k,ans; int min(int x,int y)
{
return(x<y?x:y);
} void init()
{
int i,j;
scanf("%d%d%d",&n,&m,&k);
for(i=;i<=n;i++)
for(j=;j<=m;j++)
scanf("%d",&a[i][j]),b[i][j]=a[i][j];
} int q[maxn][],head,tail; void work()
{
int i,j;
for(i=;i<=n;i++)
{
head=;tail=;
for(j=;j<=m;j++)
{
while(tail>=head & q[tail][]<=a[i][j])--tail;
tail++;
q[tail][]=j;
q[tail][]=a[i][j];
while(q[head][]<=j-k)head++;
a[i][j]=q[head][];
}
}
for(j=;j<=m;j++)
{
head=;tail=;
for(i=;i<=n;i++)
{
while(tail>=head & q[tail][]<=a[i][j])tail--;
tail++;
q[tail][]=i;
q[tail][]=a[i][j];
while(q[head][]<=i-k)head++;
a[i][j]=q[head][];
}
}
for(i=;i<=n;i++)
{
head=;tail=;
for(j=;j<=m;j++)
{
while(tail>=head & q[tail][]>=b[i][j])tail--;
tail++;
q[tail][]=j;
q[tail][]=b[i][j];
while(q[head][]<=j-k)head++;
b[i][j]=q[head][];
}
}
for(j=;j<=m;j++)
{
head=;tail=;
for(i=;i<=n;i++)
{
while(tail>=head & q[tail][]>=b[i][j])tail--;
tail++;
q[tail][]=i;
q[tail][]=b[i][j];
while(q[head][]<=i-k)head++;
b[i][j]=q[head][];
}
}
ans=;
for(i=k;i<=n;i++)
for(j=k;j<=m;j++)
ans=min(ans,a[i][j]-b[i][j]);
printf("%d",ans);
} int main()
{
init();
work();
return ;
}

1047: [HAOI2007]理想的正方形 - BZOJ的更多相关文章

  1. bzoj 1047 : [HAOI2007]理想的正方形 单调队列dp

    题目链接 1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2369  Solved: 1266[Submi ...

  2. BZOJ 1047: [HAOI2007]理想的正方形( 单调队列 )

    单调队列..先对每一行扫一次维护以每个点(x, y)为结尾的长度为n的最大最小值.然后再对每一列扫一次, 在之前的基础上维护(x, y)为结尾的长度为n的最大最小值. 时间复杂度O(ab) (话说还是 ...

  3. [BZOJ 1047] [HAOI2007] 理想的正方形 【单调队列】

    题目链接:BZOJ - 1047 题目分析 使用单调队列在 O(n^2) 的时间内求出每个 n * n 正方形的最大值,最小值.然后就可以直接统计答案了. 横向有 a 个单调队列(代码中是 Q[1] ...

  4. 【BZOJ】1047: [HAOI2007]理想的正方形(单调队列/~二维rmq+树状数组套树状数组)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1047 树状数组套树状数组真心没用QAQ....首先它不能修改..而不修改的可以用单调队列做掉,而且更 ...

  5. BZOJ 1047: [HAOI2007]理想的正方形

    题目 单调队列是个很神奇的东西,我以前在博客写过(吧) 我很佩服rank里那些排前几的大神,700ms做了时限10s的题,简直不能忍.(但是我还是不会写 我大概一年半没写单调队列,也有可能根本没有写过 ...

  6. BZOJ 1047: [HAOI2007]理想的正方形 单调队列瞎搞

    题意很简明吧? 枚举的矩形下边界和右端点即右下角,来确定矩形位置: 每一个纵列开一个单调队列,记录从 i-n+1 行到 i 行每列的最大值和最小值,矩形下边界向下推移的时候维护一下: 然后在记录的每一 ...

  7. bzoj 1047: [HAOI2007]理想的正方形【单调队列】

    没有复杂结构甚至不长但是写起来就很想死的代码类型 原理非常简单,就是用先用单调队列处理出mn1[i][j]表示i行的j到j+k-1列的最小值,mx1[i][j]表示i行的j到j+k-1列的最大值 然后 ...

  8. 1047: [HAOI2007]理想的正方形

    Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4075  Solved: 2277[Submit][Status][Discuss] Descript ...

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

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

随机推荐

  1. 海量小文件存储与Ceph实践

    海量小文件存储(简称LOSF,lots of small files)出现后,就一直是业界的难题,众多博文(如[1])对此问题进行了阐述与分析,许多互联网公司也针对自己的具体场景研发了自己的存储方案( ...

  2. Unity Rigidbody 刚体中的Angular Drag和Freeze Position/Rotation

    Rigidbody中 Angular Drag  (角阻力):同样指的是空气阻力,只不过是用来阻碍物体旋转的.如果设置成无限的话,物体会立即停止旋转.如果设置成0,物体在上升过程中,会发生侧翻旋转. ...

  3. C标准库函数实现之strstr(转)

    看下Linux下的实现: char *strstr(const char *s1, const char *s2) { size_t l1, l2; l2 = strlen(s2); if (!l2) ...

  4. PHP学习笔记 - 进阶篇(6)

    PHP学习笔记- 进阶篇(6) 会话控制(session与cookie) 当前的Cookie为: cookie简介 Cookie是存储在客户端浏览器中的数据,我们通过Cookie来跟踪与存储用户数据. ...

  5. 第一个Apple Watch小例子

    原文在这, 不过他说的add target按照他的说法还真没找到(估计是我的眼瞎了或者是版本不一样),还有就是好记性不如烂博客,先自己能看懂就行了. 请用Single View Application ...

  6. UML静态类图

    0,主要分为类.接口.协作.关系,这四种元素.作用:a,显示类.接口以及他们之间的静态结构和关系:b,用于描述系统的结构化设计. 1,类 CStudent +m_strName : string +S ...

  7. Linux进程调度

    原文地址: http://cchxm1978.blog.163.com/blog/static/35428253201092910491682/ 相当不错的文章,读了后收藏,多谢博主分享! ----- ...

  8. lex&yacc

    LEX: yytext 数组包含匹配模式的文本; 使词法分析程序工作的两条规则是:1. lex 模式只匹配输入字符或字符串一次.2. lex 执行当前输入的最长可能匹配的动作. 由 lex 产生的词法 ...

  9. Google的小秘密

      google有计算器的功能,例如在google中搜索25*25.lg(13)等,看会出现什么样的结果. http://www.google.com/microsoft  微软风格的入口 http: ...

  10. 探索 Java 同步机制[Monitor Object 并发模式在 Java 同步机制中的实现]

    探索 Java 同步机制[Monitor Object 并发模式在 Java 同步机制中的实现] https://www.ibm.com/developerworks/cn/java/j-lo-syn ...