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

    P2216 [HAOI2007]理想的正方形

    题目描述

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

    a,b<=1000

    分析题目: 首先可以想到一个O(a*b*n) 的解法:

    我最开始想的办法是预处理递推出矩形中的最大值和最小值,即:用maxv(i,j,k)表示以点(i,j)为左上角的边长为k的矩形中的最大值,然后用递推公式

    maxv[i][j] = max(grid[i][j], max(maxv[i+1][j+1], max(maxv[i+1][j], maxv[i][j+1])));

    但是只有50分,接下来,有两种优化方法:

    1.把n转化为log(n),用RMQ(倍增)

    2.单调队列:每一行O(b)处理,然后每一列O(a)处理,复杂度应为O(a*b)

    代码:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cctype>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    #define res register int
    #define getchar gc
    char buf[1<<18],*fc,*tc;
    inline char gc()
    {
    	if(fc==tc)
    	{
    		tc=(fc=buf)+fread(buf,1,1<<18,stdin);
    		if(tc==fc) return EOF;
    	}
    	return *fc++;
    }
    inline int read()
    {
    	int x=0,f=1; char ch;
    	while(!isdigit(ch=getchar())) if(ch=='-') f=-1;
    	while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    	return f*x;
    }
    
    const int N=1005,inf=0x3f3f3f3f;
    int a,b,n;
    int mp[N][N],X[N][N],x[N][N],Y[N][N],y[N][N];
    //大写最大值,小写最小值
    //x[i][j]:第i行j~j+n-1的最小值
    //y[i][j]:从mp[i~i+n-1][j~j+n-1]的最小值 
    
    int Q[N],q[N],h,t,H,T;//head -> tail  单调  
    
    inline void solve()
    {
        for(res i=1 ; i<=a ; ++i)
        {
            h=t=H=T=Q[1]=q[1]=1;
            for(res j=2 ; j<=b ; ++j)
            {
                while(H<=T&&mp[i][j]>=mp[i][Q[T]]) --T;//维护单调性 
                while(h<=t&&mp[i][j]<=mp[i][q[t]]) --t;
                q[++t]=j; Q[++T]=j; 	
                //维护大小 
                while(j-Q[H]>=n) ++H;  
                while(j-q[h]>=n) ++h;
                if(j>=n) X[i][j-n+1]=mp[i][Q[H]],x[i][j-n+1]=mp[i][q[h]]; 
            }
        }
        
        for(res j=1 ; j+n-1<=b ; ++j)//维护j~j+n-1列 
        {
            h=t=H=T=Q[1]=q[1]=1;
            for(res i=2 ; i<=a ; ++i)
            {
                while(H<=T&&X[i][j]>=X[Q[T]][j]) --T;
                while(h<=t&&x[i][j]<=x[q[t]][j]) --t;
                Q[++T]=i; q[++t]=i;
                while(i-Q[H]>=n) ++H;
                while(i-q[h]>=n) ++h;
                if(i>=n) Y[i-n+1][j]=X[Q[H]][j],y[i-n+1][j]=x[q[h]][j];
            }
        }
    }
    
    int main()
    {
        a=read(); b=read(); n=read();
        for(res i=1 ; i<=a ; ++i) 
    		for(res j=1 ; j<=b ; ++j) mp[i][j]=read();
        solve();
        int ans=inf;
        for(res i=1 ; i+n-1<=a ; ++i)
            for(res j=1 ; j+n-1<=b ; ++j)
                ans=min(ans,Y[i][j]-y[i][j]);
        
        printf("%d
    ",ans);
        return 0;
    }
    

      

  • 相关阅读:
    笔记64 Spring Boot快速入门(四)
    笔记63 Spring Boot快速入门(三)
    笔记62 Spring Boot快速入门(二)
    笔记61 Spring Boot快速入门(一)
    笔记60 Spring+Mybatis整合
    笔记59 Spring+Hibernate整合(二)
    【转】单点登录原理与实现
    【转】大型网站架构演变和知识体系
    Eclipse下绿色安装插件Aptana、Swing
    zeromq源码分析笔记之准备(0)
  • 原文地址:https://www.cnblogs.com/wmq12138/p/10691168.html
Copyright © 2011-2022 走看看