zoukankan      html  css  js  c++  java
  • 洛谷P2216 [HAOI2007] 理想的正方形

    题目描述

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

    输入输出格式

    输入格式:

     

    第一行为3个整数,分别表示a,b,n的值

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

     

    输出格式:

     

    仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。

     

    输入输出样例

    输入样例#1:
    5 4 2
    1 2 5 6
    0 17 16 0
    16 17 2 1
    2 10 2 1
    1 2 2 2
    
    输出样例#1:
    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

    跑两遍DP,第一遍处理出行i内以j为端点的长度为n的区间内的最大值和最小值。

    第二遍DP,根据之前处理出的一维区间最值,DP出二维区间最值。

    然后枚举区间端点,找最优解。

    需要用单调队列优化

     1 /*by SilverN*/
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<cmath>
     7 #include<vector>
     8 using namespace std;
     9 const int mxn=1010;
    10 int read(){
    11     int x=0,f=1;char ch=getchar();
    12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    14     return x*f;
    15 }
    16 int mp[mxn][mxn];
    17 int fmx[mxn][mxn],fmi[mxn][mxn];
    18 int dpmx[mxn][mxn],dpmi[mxn][mxn];
    19 int a,b,n;
    20 void work(){
    21     
    22 }
    23 int q1[mxn],hd1=0,tl1=0;
    24 int q2[mxn],hd2=0,tl2=0;
    25 int main(){
    26     a=read();b=read();n=read();
    27     int i,j;
    28     memset(fmi,0x3f,sizeof fmi);
    29     for(i=1;i<=a;i++){
    30         hd1=hd2=1;
    31         tl1=tl2=0;
    32         for(j=1;j<=b;j++){
    33             mp[i][j]=read();
    34             while(hd1<=tl1 && j-q1[hd1]>=n)hd1++;
    35             while(hd1<=tl1 && mp[i][j]>=mp[i][q1[tl1]]) tl1--;
    36             q1[++tl1]=j;
    37             fmx[i][j]=mp[i][q1[hd1]];
    38             //max
    39             while(hd2<=tl2 && j-q2[hd2]>=n)hd2++;
    40             while(hd2<=tl2 && mp[i][j]<=mp[i][q2[tl2]]) tl2--;
    41             q2[++tl2]=j;
    42             fmi[i][j]=mp[i][q2[hd2]];
    43             //min
    44         }
    45     }
    46     memset(dpmi,0x3f,sizeof dpmi);
    47     hd1=hd2=1;tl1=tl2=0;
    48     for(j=1;j<=b;j++){
    49         hd1=hd2=1;tl1=tl2=0;
    50         for(i=1;i<=a;i++){
    51             while(hd1<=tl1 && i-q1[hd1]>=n)hd1++;
    52             while(hd1<=tl1 && fmx[i][j]>=fmx[q1[tl1]][j])tl1--;
    53             q1[++tl1]=i;
    54             dpmx[i][j]=fmx[q1[hd1]][j];
    55             
    56             while(hd2<=tl2 && i-q2[hd2]>=n)hd2++;
    57             while(hd2<=tl2 && fmi[i][j]<=fmi[q2[tl2]][j])tl2--;
    58             q2[++tl2]=i;
    59             dpmi[i][j]=fmi[q2[hd2]][j];
    60             
    61         }
    62     }
    63     int ans=0x3f3f3f3f;
    64     for(i=n;i<=a;i++)
    65      for(j=n;j<=b;j++){
    66          ans=min(ans,dpmx[i][j]-dpmi[i][j]);
    67      }
    68     printf("%d
    ",ans);
    69     return 0;
    70 }
  • 相关阅读:
    hdoj 2803 The MAX【简单规律题】
    hdoj 2579 Dating with girls(2)【三重数组标记去重】
    hdoj 1495 非常可乐【bfs隐式图】
    poj 1149 PIGS【最大流经典建图】
    poj 3281 Dining【拆点网络流】
    hdoj 3572 Task Schedule【建立超级源点超级汇点】
    hdoj 1532 Drainage Ditches【最大流模板题】
    poj 1459 Power Network【建立超级源点,超级汇点】
    hdoj 3861 The King’s Problem【强连通缩点建图&&最小路径覆盖】
    hdoj 1012 u Calculate e
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/5982430.html
Copyright © 2011-2022 走看看