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

    BZOJ1047: [HAOI2007]理想的正方形

    Description

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

    Input

      第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。

    每行相邻两数之间用一空格分隔。
    100%的数据2<=a,b<=1000,n<=a,n<=b,n<=1000

    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

    题解Here!

    一看题——这绝对是$DP$!
    然后这个$flag$在$3s$之后被推翻了。
    数据范围$n,m<=10^3,q<=10^2$。。。
    那就直接单调队列维护每行每列,然后暴力求出最小值就好了啊!
    单调队列是啥不用多说。
    设$f[i][j]$表示第$i$行中$[j,j+q-1]$之间的最大值,$g[i][j]$表示第$i$行中$[j,j+q-1]$之间的最小值。
    显然直接维护就好。
    然后再套一个单调队列:
    设$maxn[i][j]$表示$f[i][j]$中$[i,i+q-1]$行的第$j$列的最大值,$maxn[i][j]$表示$g[i][j]$中$[i,i+q-1]$行的第$j$列的最小值。
    显然可以同上,直接单调队列维护就好。
    然后暴力求出$maxn[i][j]-minn[i][j]$的最小值。
    至于单调队列怎么实现。。。
    我偷个懒,直接用$STL$——$deque$,双端队列。
    附代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<deque>
    #define MAXN 1010
    using namespace std;
    deque<int> que_max,que_min;
    int n,m,q,ans=2147483646;
    int val[MAXN][MAXN],f[MAXN][MAXN],g[MAXN][MAXN],maxn[MAXN][MAXN],minn[MAXN][MAXN];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    void work(){
    	for(int j=1;j<=m-q+1;j++){
    		que_max.clear();que_min.clear();
    		que_max.push_back(1);que_min.push_back(1);
    		for(int i=2;i<=n;i++){
    			while(!que_max.empty()&&f[i][j]>=f[que_max.back()][j])que_max.pop_back();
    			while(!que_min.empty()&&g[i][j]<=g[que_min.back()][j])que_min.pop_back();
    			que_max.push_back(i);
    			que_min.push_back(i);
    			while(i-que_max.front()>=q)que_max.pop_front();
    			while(i-que_min.front()>=q)que_min.pop_front();
    			if(i>=q){
    				maxn[i-q+1][j]=f[que_max.front()][j];
    				minn[i-q+1][j]=g[que_min.front()][j];
    			}
    		}
    	}
    	for(int i=1;i<=n-q+1;i++)
    	for(int j=1;j<=m-q+1;j++)
    	ans=min(ans,maxn[i][j]-minn[i][j]);
    	printf("%d
    ",ans);
    }
    void init(){
    	n=read();m=read();q=read();
    	for(int i=1;i<=n;i++)
    	for(int j=1;j<=m;j++)
    	val[i][j]=read();
    	for(int i=1;i<=n;i++){
    		que_max.clear();que_min.clear();
    		que_max.push_back(1);que_min.push_back(1);
    		for(int j=2;j<=m;j++){
    			while(!que_max.empty()&&val[i][j]>=val[i][que_max.back()])que_max.pop_back();
    			while(!que_min.empty()&&val[i][j]<=val[i][que_min.back()])que_min.pop_back();
    			que_max.push_back(j);
    			que_min.push_back(j);
    			while(j-que_max.front()>=q)que_max.pop_front();
    			while(j-que_min.front()>=q)que_min.pop_front();
    			if(j>=q){
    				f[i][j-q+1]=val[i][que_max.front()];
    				g[i][j-q+1]=val[i][que_min.front()];
    			}
    		}
    	}
    }
    int main(){
    	init();
    	work();
        return 0;
    }
    
  • 相关阅读:
    mysql主从配置
    前台使用复杂json
    eclipse打包非web项目的整合了spring和mybaits的pom项目,打包可以运行的jar
    Select
    sqlcmd踩坑笔记(环境Ubuntu18.04)
    等待
    戴锦华访谈:小鲜肉 大女主 腐文化的流行 当代女性的生存现状和困境
    CREATE
    语法约定和标识符
    SQL Server应用目录
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9866870.html
Copyright © 2011-2022 走看看