• HAOI2007 理想的正方形


    1047: [HAOI2007]理想的正方形

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1402  Solved: 738
    [Submit][Status]

    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

    HINT

    题解:

    真是一道好题!

    我一开始只想到了二维的RMQ,分析了一下时间和空间复杂度,感觉都承受不起……

    一看题解,恍然大悟,因为该问题的特殊性,固定了以n为边长,所以只要用单调队列即可,RMQ多余了,用不到RMQ的优点

    (而且,我参看的大牛的代码很巧妙的使代码量降了下来,如下这是一种技巧,以后要掌握)

    代码:

     1 uses math;
     2 var f:array[1..2,0..1100,0..1100] of longint;
     3     g,c:array[0..1100,0..1100] of longint;
     4     i,j,a,b,n,ans:longint;
     5 procedure init;
     6  begin
     7   readln(a,b,n);
     8   for i:=1 to a do
     9    begin
    10     for j:=1 to b do read(c[i,j]);
    11     readln;
    12    end;
    13  end;
    14 procedure work(x:longint);
    15  var i,j,l,r:longint;
    16      q:array[0..1500] of longint;
    17  begin
    18  for i:=1 to a do
    19   begin
    20    fillchar(q,sizeof(q),0);
    21    l:=1;r:=0;
    22    for j:=1 to b do
    23     begin
    24     while (l<=r) and (c[i,q[r]]<=c[i,j]) do dec(r);
    25     inc(r);q[r]:=j;
    26     while (l<r) and (q[l]<j-n+1) do inc(l);
    27     g[i,j]:=c[i,q[l]];
    28     end;
    29   end;
    30  for i:=1 to b do
    31   begin
    32    fillchar(q,sizeof(q),0);
    33    l:=1;r:=0;
    34    for j:=1 to a do
    35     begin
    36     while (l<=r) and (g[q[r],i]<=g[j,i]) do dec(r);
    37     inc(r);q[r]:=j;
    38     while (l<r) and (q[l]<j-n+1) do inc(l);
    39     f[x,j,i]:=g[q[l],i];
    40     end;
    41   end;
    42  end;
    43 procedure main;
    44  begin
    45  work(1);
    46  for i:=1 to a do
    47   for j:=1 to b do
    48    c[i,j]:=0-c[i,j];
    49  work(2);
    50  ans:=maxlongint;
    51  for i:=n to a do
    52   for j:=n to b do
    53    ans:=min(ans,f[1,i,j]+f[2,i,j]);
    54  writeln(ans);
    55  end;
    56 begin
    57  init;
    58  main;
    59 end.
    View Code
  • 相关阅读:
    多维数组的索引与切片
    多维数组
    开学第一课Java考试
    大一第九周学习体会
    大一第八周学习体会
    大一第七周学习体会
    大一第六周学习体会
    大一第五周学习体会
    《大道至简》读后感
    大一暑假第四周学习体会
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/3809864.html
Copyright © 2020-2023  润新知