zoukankan      html  css  js  c++  java
  • 洛谷 P2216 [HAOI2007]理想的正方形 || 二维RMQ的单调队列

    题目

    这个题的算法核心就是求出以i,j为左上角,边长为n的矩阵中最小值和最大值。最小和最大值的求法类似。

    单调队列做法:

    以最小值为例:

    q1[i][j]表示第i行上,从j列开始的n列的最小值。
    $q1[i][j]=min(x[i][j],x[i][j+1],...,x[i][j+n-1])$
    $q1[i][1]=min(x[i][1],x[i][2],...,x[i][n])$
    $q1[i][2]=min(x[i][2],x[i][3],...,x[i][n+1])$
    类似滑动窗口,因此直接枚举行,对于每一行单调队列处理即可。

    q2[i][j]表示以第i行第j列为左上角的边长为n的矩阵的最小值
    $q2[i][j]=min(q1[i][j],q1[i+1][j],...,q1[i+n-1][j])$
    $q2[1][j]=min(q1[1][j],q1[2][j],...,q1[n][j])$
    $q2[2][j]=min(q1[2][j],q1[3][j],...,q2[n+1][j])$
    显然又可以用单调队列处理。总时间复杂度$O(n^2)$

    (额外)更简短的做法(二维ST表,$O(n^2;log;n)$):

    (由于要求的是正方形,因此可以$O(n^2;log;n)$,一般应该是$O({(n;log;n)}^2)$)

    用f[i][j][k]来表示横纵坐标分别为i,j开始到i+2^k-1,j+2^k-1的整个矩阵(正方形)中的最大值

    https://www.luogu.org/wiki/show?name=%E9%A2%98%E8%A7%A3+P2216

    笔记:

    1.这道题一开始想到了可能跟单调队列有关系,但是并没有想清楚。想了很久后,把q1和q2的关系式列了出来,一切就明朗了。

    2.求最小值的单调队列队首(l)最小,队尾(r)最大,l<r。求最大值的单调队列队首(l)最大,队尾(r)最小,l<r。

    求最小值的单调队列
    2 3 5 4 6 1
    1. 2
    2. 2 3
    3. 2 3 5
    4. 2 3 4
    5. 2 3 4 6
    6. 1

    3.单调队列的调试还算方便,只需要开着对单调队列的变量查看,观察内部元素是否正常就行了。

     1 #include<cstdio>
     2 #define min(a,b) ((a)>(b)?(b):(a))
     3 typedef long long LL;
     4 LL a,b,n;
     5 LL x[1010][1010];
     6 LL q1min[1010][1010],q1max[1010][1010],q2min[1010][1010],q2max[1010][1010];
     7 LL tmpmin[1010],tmpmax[1010],lmin,rmin,lmax,rmax,anss=0x3f3f3f3f3f3f3f3f;
     8 int main()
     9 {
    10     LL i,j;
    11     scanf("%lld%lld%lld",&a,&b,&n);
    12     for(i=1;i<=a;i++)
    13         for(j=1;j<=b;j++)
    14             scanf("%lld",&x[i][j]);
    15     for(i=1;i<=a;i++)
    16     {
    17         lmin=rmin=lmax=rmax=0;
    18         for(j=1;j<=n;j++)
    19         {
    20             while(rmin>lmin&&x[i][tmpmin[rmin-1]]>=x[i][j])    rmin--;
    21             tmpmin[rmin++]=j;
    22             while(rmax>lmax&&x[i][tmpmax[rmax-1]]<=x[i][j])    rmax--;
    23             tmpmax[rmax++]=j;
    24         }
    25         q1min[i][1]=x[i][tmpmin[lmin]];
    26         q1max[i][1]=x[i][tmpmax[lmax]];
    27         for(j=n+1;j<=b;j++)
    28         {
    29             if(rmin>lmin&&tmpmin[lmin]<=j-n)    lmin++;
    30             if(rmax>lmax&&tmpmax[lmax]<=j-n)    lmax++;
    31             while(rmin>lmin&&x[i][tmpmin[rmin-1]]>=x[i][j])    rmin--;
    32             tmpmin[rmin++]=j;
    33             while(rmax>lmax&&x[i][tmpmax[rmax-1]]<=x[i][j])    rmax--;
    34             tmpmax[rmax++]=j;
    35             q1min[i][j-n+1]=x[i][tmpmin[lmin]];
    36             q1max[i][j-n+1]=x[i][tmpmax[lmax]];
    37         }
    38     }
    39     for(i=1;i<=b;i++)
    40     {
    41         lmin=rmin=lmax=rmax=0;
    42         for(j=1;j<=n;j++)
    43         {
    44             while(rmin>lmin&&q1min[tmpmin[rmin-1]][i]>=q1min[j][i])    rmin--;
    45             tmpmin[rmin++]=j;
    46             while(rmax>lmax&&q1max[tmpmax[rmax-1]][i]<=q1max[j][i])    rmax--;
    47             tmpmax[rmax++]=j;
    48         }
    49         q2min[1][i]=q1min[tmpmin[lmin]][i];
    50         q2max[1][i]=q1max[tmpmax[lmax]][i];
    51         for(j=n+1;j<=a;j++)
    52         {
    53             if(rmin>lmin&&tmpmin[lmin]<=j-n)    lmin++;
    54             if(rmax>lmax&&tmpmax[lmax]<=j-n)    lmax++;
    55             while(rmin>lmin&&q1min[tmpmin[rmin-1]][i]>=q1min[j][i])    rmin--;
    56             tmpmin[rmin++]=j;
    57             while(rmax>lmax&&q1max[tmpmax[rmax-1]][i]<=q1max[j][i])    rmax--;
    58             tmpmax[rmax++]=j;
    59             q2min[j-n+1][i]=q1min[tmpmin[lmin]][i];
    60             q2max[j-n+1][i]=q1max[tmpmax[lmax]][i];
    61         }
    62     }
    63     for(i=1;i<=a-n+1;i++)
    64         for(j=1;j<=b-n+1;j++)
    65             anss=min(anss,q2max[i][j]-q2min[i][j]);
    66     printf("%lld",anss);
    67     return 0;
    68 }
  • 相关阅读:
    SQL 学习笔记(一)联表查询
    .NET (OleDb) Access 各个版本的连接字符口串
    加油站
    程序员的编程套路
    落单的数
    读《怎样解题》
    使用org-mode写cnblogs博客
    Emacs 25.1 error solved: url-http-create-request: Multibyte text in HTTP request
    二进制表示小数
    快速幂
  • 原文地址:https://www.cnblogs.com/hehe54321/p/7693849.html
Copyright © 2011-2022 走看看