zoukankan      html  css  js  c++  java
  • [HAOI 2007]理想的正方形

    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

    HINT

    问题规模
    (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$的做法。

    二维的$RMQ$求正方形内的最值,和一维没什么不同,只是倍增以及询问的时候要分四块。

     1 #include<cmath>
     2 #include<ctime>
     3 #include<stack>
     4 #include<queue>
     5 #include<string>
     6 #include<cstdio>
     7 #include<cstring>
     8 #include<cstdlib>
     9 #include<iostream>
    10 #include<algorithm>
    11  using namespace std;
    12 const int N=1000;
    13 
    14 int a,b,n,op;
    15 int minn[N+5][N+5][15],maxn[N+5][N+5][15];
    16 
    17 int main()
    18 {
    19     scanf("%d%d%d",&a,&b,&n);
    20     for (int i=1;i<=a;i++)
    21         for (int j=1;j<=b;j++)
    22         {
    23             scanf("%d",&minn[i][j][0]);
    24             maxn[i][j][0]=minn[i][j][0];
    25         }
    26     op=log2(n);
    27     for (int t=1;t<=op;t++)
    28         for (int i=1;i+(1<<t)-1<=a;i++)
    29             for (int j=1;j+(1<<t)-1<=b;j++)
    30             {
    31                 minn[i][j][t]=min(minn[i][j][t-1],minn[i][j+(1<<t-1)][t-1]);
    32                 minn[i][j][t]=min(minn[i][j][t],minn[i+(1<<t-1)][j][t-1]);
    33                 minn[i][j][t]=min(minn[i][j][t],minn[i+(1<<t-1)][j+(1<<t-1)][t-1]);
    34                 maxn[i][j][t]=max(maxn[i][j][t-1],maxn[i][j+(1<<t-1)][t-1]);
    35                 maxn[i][j][t]=max(maxn[i][j][t],maxn[i+(1<<t-1)][j][t-1]);
    36                 maxn[i][j][t]=max(maxn[i][j][t],maxn[i+(1<<t-1)][j+(1<<t-1)][t-1]);
    37             }
    38     int ansmax,ansmin,ans=2e9;
    39     for (int i=1;i+n-1<=a;i++)
    40         for (int j=1;j+n-1<=b;j++)
    41         {
    42             ansmax=max(maxn[i][j][op],maxn[i][j+n-(1<<op)][op]);
    43             ansmax=max(ansmax,maxn[i+n-(1<<op)][j][op]);
    44             ansmax=max(ansmax,maxn[i+n-(1<<op)][j+n-(1<<op)][op]);
    45             ansmin=min(minn[i][j][op],minn[i][j+n-(1<<op)][op]);
    46             ansmin=min(ansmin,minn[i+n-(1<<op)][j][op]);
    47             ansmin=min(ansmin,minn[i+n-(1<<op)][j+n-(1<<op)][op]);
    48             ans=min(ans,ansmax-ansmin);
    49         }
    50     printf("%d
    ",ans);
    51     return 0;
    52 }
  • 相关阅读:
    HDU4366 Successor 线段树+预处理
    POJ2823 Sliding Window 单调队列
    HDU寻找最大值 递推求连续区间
    UVA846 Steps 二分查找
    HDU3415 Max Sum of MaxKsubsequence 单调队列
    HDU时间挑战 树状数组
    UVA10168 Summation of Four Primes 哥德巴赫猜想
    UESTC我要长高 DP优化
    HDUChess 递推
    HDU4362 Dragon Ball DP+优化
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7262761.html
Copyright © 2011-2022 走看看