zoukankan      html  css  js  c++  java
  • 1047: [HAOI2007]理想的正方形

    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的正方形的信息都存到左上角了,扫一遍就行了

     1 const
     2     maxn=1010;
     3 var
     4     a,b:array[0..maxn,0..maxn]of longint;
     5     n,m,k:longint;
     6 
     7 procedure down(var x:longint;y:longint);
     8 begin
     9     if x>y then x:=y;
    10 end;
    11 
    12 procedure up(var x,y:longint);
    13 begin
    14     if x<y then x:=y;
    15 end;
    16 
    17 procedure main;
    18 var
    19     i,j,l,s,ans:longint;
    20 begin
    21     read(n,m,k);
    22     for i:=1 to n do
    23       for j:=1 to m do
    24         begin
    25           read(a[i,j]);
    26           b[i,j]:=a[i,j];
    27         end;
    28     l:=1;
    29     while l<k do
    30       begin
    31         for i:=1 to n do
    32           for j:=1 to m do
    33             begin
    34               s:=j+l;
    35               down(s,m-l+1);
    36               down(s,j+k-l);
    37               up(a[i,j],a[i,s]);
    38               down(b[i,j],b[i,s]);
    39             end;
    40         l:=l<<1;
    41       end;
    42     l:=1;
    43     while l<k do
    44       begin
    45         for i:=1 to n do
    46           for j:=1 to m do
    47             begin
    48               s:=i+l;
    49               down(s,n-l+1);
    50               down(s,i+k-l);
    51               up(a[i,j],a[s,j]);
    52               down(b[i,j],b[s,j]);
    53             end;
    54         l:=l<<1;
    55       end;
    56     ans:=maxlongint;
    57     for i:=1 to n-k+1 do
    58       for j:=1 to m-k+1 do
    59         down(ans,a[i,j]-b[i,j]);
    60     write(ans);
    61 end;
    62 
    63 begin
    64     main;
    65 end.
    View Code

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

      1 const
      2     maxn=1010;
      3 var
      4     a,b:array[0..maxn,0..maxn]of longint;
      5     n,m,k,ans:longint;
      6  
      7 function min(x,y:longint):longint;
      8 begin
      9     if x<y then exit(x);
     10     exit(y);
     11 end;
     12  
     13 procedure init;
     14 var
     15     i,j:longint;
     16 begin
     17     read(n,m,k);
     18     for i:=1 to n do
     19       for j:=1 to m do
     20         begin
     21           read(a[i,j]);
     22           b[i,j]:=a[i,j];
     23         end;
     24 end;
     25  
     26 var
     27     q:array[0..maxn,0..1]of longint;
     28     head,tail:longint;
     29  
     30 procedure work;
     31 var
     32     i,j:longint;
     33 begin
     34     for i:=1 to n do
     35       begin
     36         head:=1;
     37         tail:=0;
     38         for j:=1 to m do
     39           begin
     40             while (tail>=head) and (q[tail,1]<=a[i,j]) do
     41               dec(tail);
     42             inc(tail);
     43             q[tail,0]:=j;
     44             q[tail,1]:=a[i,j];
     45             while q[head,0]<=j-k do
     46               inc(head);
     47             a[i,j]:=q[head,1];
     48           end;
     49       end;
     50     for j:=1 to m do
     51       begin
     52         head:=1;
     53         tail:=0;
     54         for i:=1 to n do
     55           begin
     56             while (tail>=head) and (q[tail,1]<=a[i,j]) do
     57               dec(tail);
     58             inc(tail);
     59             q[tail,0]:=i;
     60             q[tail,1]:=a[i,j];
     61             while q[head,0]<=i-k do
     62               inc(head);
     63             a[i,j]:=q[head,1];
     64           end;
     65       end;
     66     for i:=1 to n do
     67       begin
     68         head:=1;
     69         tail:=0;
     70         for j:=1 to m do
     71           begin
     72             while (tail>=head) and (q[tail,1]>=b[i,j]) do
     73               dec(tail);
     74             inc(tail);
     75             q[tail,0]:=j;
     76             q[tail,1]:=b[i,j];
     77             while q[head,0]<=j-k do
     78               inc(head);
     79             b[i,j]:=q[head,1];
     80           end;
     81       end;
     82     for j:=1 to m do
     83       begin
     84         head:=1;
     85         tail:=0;
     86         for i:=1 to n do
     87           begin
     88             while (tail>=head) and (q[tail,1]>=b[i,j]) do
     89               dec(tail);
     90             inc(tail);
     91             q[tail,0]:=i;
     92             q[tail,1]:=b[i,j];
     93             while q[head,0]<=i-k do
     94               inc(head);
     95             b[i,j]:=q[head,1];
     96           end;
     97       end;
     98     ans:=maxlongint;
     99     for i:=k to n do
    100       for j:=k to m do
    101         ans:=min(ans,a[i,j]-b[i,j]);
    102     write(ans);
    103 end;
    104  
    105 begin
    106     init;
    107     work;
    108 end.
    View Code

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

     1 #include<cstdio>
     2 using namespace std;
     3 
     4 const int maxn=1510;
     5 
     6 int a[maxn][maxn],b[maxn][maxn],n,m,k,ans;
     7 
     8 int min(int x,int y)
     9 {
    10     return(x<y?x:y);
    11 }
    12 
    13 void init()
    14 {
    15     int i,j;
    16     scanf("%d%d%d",&n,&m,&k);
    17     for(i=1;i<=n;i++)
    18         for(j=1;j<=m;j++)
    19         scanf("%d",&a[i][j]),b[i][j]=a[i][j];
    20 }
    21 
    22 int q[maxn][2],head,tail;
    23 
    24 void work()
    25 {
    26     int i,j;
    27     for(i=1;i<=n;i++)
    28     {
    29         head=1;tail=0;
    30         for(j=1;j<=m;j++)
    31         {
    32             while(tail>=head & q[tail][1]<=a[i][j])--tail;
    33             tail++;
    34             q[tail][0]=j;
    35             q[tail][1]=a[i][j];
    36             while(q[head][0]<=j-k)head++;
    37             a[i][j]=q[head][1];
    38         }
    39     }
    40     for(j=1;j<=m;j++)
    41     {
    42         head=1;tail=0;
    43         for(i=1;i<=n;i++)
    44         {
    45             while(tail>=head & q[tail][1]<=a[i][j])tail--;
    46             tail++;
    47             q[tail][0]=i;
    48             q[tail][1]=a[i][j];
    49             while(q[head][0]<=i-k)head++;
    50             a[i][j]=q[head][1];
    51         }
    52     }
    53     for(i=1;i<=n;i++)
    54     {
    55         head=1;tail=0;
    56         for(j=1;j<=m;j++)
    57         {
    58             while(tail>=head & q[tail][1]>=b[i][j])tail--;
    59             tail++;
    60             q[tail][0]=j;
    61             q[tail][1]=b[i][j];
    62             while(q[head][0]<=j-k)head++;
    63             b[i][j]=q[head][1];
    64         }
    65     }
    66     for(j=1;j<=m;j++)
    67     {
    68         head=1;tail=0;
    69         for(i=1;i<=n;i++)
    70         {
    71             while(tail>=head & q[tail][1]>=b[i][j])tail--;
    72             tail++;
    73             q[tail][0]=i;
    74             q[tail][1]=b[i][j];
    75             while(q[head][0]<=i-k)head++;
    76             b[i][j]=q[head][1];
    77         }
    78     }
    79     ans=2000000000;
    80     for(i=k;i<=n;i++)
    81         for(j=k;j<=m;j++)
    82         ans=min(ans,a[i][j]-b[i][j]);
    83     printf("%d",ans);
    84 }
    85 
    86 int main()
    87 {
    88     init();
    89     work();
    90     return 0;
    91 }
    View Code
  • 相关阅读:
    Python校验文件MD5值
    no acceptable C compiler found in $PATH解决办法
    PRD是什么
    项目中PO、PM的职责区分
    vue-cli中打包之后css加载顺序有错
    vue-cli中打包图片路径错误
    vue2.0的父子组件数据传递
    vue中style的用法
    vue中class的用法
    angular淘宝购物车案例
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3650468.html
Copyright © 2011-2022 走看看