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

    Solution:

      本题单调队列(当然也可以倍增)。

      如果是一维的情况,就是经典的滑动窗口求极值的问题了。

      考虑二维的情况,我们在每行都跑下单调队列,处理出$(i,j)$往左$n$个位置的极值。

      再在处理出的$(i,j)$的行极值上,以每列的情况跑下单调队列,就能处理出$(i,j)$为右下角所在的$n*n$矩形内的极值了。

    代码:

    /*Code by 520 -- 9.19*/
    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define RE register
    #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
    using namespace std;
    const int N=1005;
    int a,b,n,l1,r1,l2,r2,mp[N][N],x[N][N][2],y[N][N][2],q[N][2],ans=0x7fffffff;
    
    int gi(){
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-') x=getchar();
        if(x=='-') x=getchar(),f=1;
        while(x>='0'&&x<='9') a=(a<<3)+(a<<1)+(x^48),x=getchar();
        return f?-a:a;
    }
    
    int main(){
        a=gi(),b=gi(),n=gi();
        For(i,1,a) For(j,1,b) mp[i][j]=gi();
        For(i,1,a) {
            l1=1,r1=0,l2=1,r2=0;
            For(j,1,b) {
                while(l1<=r1&&mp[i][q[r1][0]]>=mp[i][j]) r1--;
                q[++r1][0]=j;
                while(l2<=r2&&mp[i][q[r2][1]]<=mp[i][j]) r2--;
                q[++r2][1]=j;
                while(q[l1][0]<=j-n) l1++;
                while(q[l2][1]<=j-n) l2++;
                if(j>=n) x[i][j][0]=mp[i][q[l1][0]],x[i][j][1]=mp[i][q[l2][1]];
            }
        }
        For(j,n,b) {
            l1=1,r1=0,l2=1,r2=0;
            For(i,1,a) {
                while(l1<=r1&&x[q[r1][0]][j][0]>=x[i][j][0]) r1--;
                q[++r1][0]=i;
                while(l2<=r2&&x[q[r2][1]][j][1]<=x[i][j][1]) r2--;
                q[++r2][1]=i;
                while(q[l1][0]<=i-n) l1++;
                while(q[l2][1]<=i-n) l2++;
                if(i>=n) ans=min(ans,x[q[l2][1]][j][1]-x[q[l1][0]][j][0]);
            }
        }
        cout<<ans;
        return 0;    
    }
  • 相关阅读:
    【文学文娱】《屌丝逆袭》-出任CEO、迎娶白富美、走上人生巅峰
    天纵英才-阿里巴巴《马云》
    我的《大宋王朝》
    《1024 程序员节》—我喂自己袋盐
    【文学文娱】《失控》读后感
    《由河南人--首富许家印说起》
    《将博客搬至CSDN》
    【置顶】技术每天一点点--2017.09-2018.10月
    saltstack的简单搭建
    rabbitMQ基础应用
  • 原文地址:https://www.cnblogs.com/five20/p/9679102.html
Copyright © 2011-2022 走看看