洛谷P2216 [HAOI2007]理想的正方形 || 洛谷P2219 [HAOI2007]修筑绿化带【单调队列】

洛谷P2216 [HAOI2007]理想的正方形

Time Limit: 10 Sec
Memory Limit: 162 MB

Description

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

Input

第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每
行相邻两数之间用一空格分隔。
100%的数据2<=a,b<=1000,n<=a,n<=b,n<=1000

Output

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


题目分析

m x [ i ] [ j ] , m i [ i ] [ j ] mx[i][j],mi[i][j] mx[i][j]mi[i][j]分别保存矩阵中第i行第j-n+1列到第j列的最大值与最小值
这两个数组可以用一次单调队列预处理出

然后对于每一列j
我们分别求出 m a x ( m x [ i − n + 1 ] [ j ] — m x [ i ] [ j ] ) max(mx[i-n+1][j]—mx[i][j]) max(mx[in+1][j]mx[i][j]) m i n ( m i [ i − n + 1 ] [ j ] — m i [ i ] [ j ] ) ( n &lt; = i &lt; = a ) min(mi[i-n+1][j]—mi[i][j])(n&lt;=i&lt;=a) min(mi[in+1][j]mi[i][j])(n<=i<=a)
这样就相当于得到了矩阵 ( i − n + 1 , j − n + 1 ) , ( i , j ) (i-n+1,j-n+1),(i,j) (in+1,jn+1)(i,j)中的最大值与最小值


代码有点乱=_=

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
 
int read()
{
    int f=1,x=0;
    char ss=getchar();
    while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
    while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
    return f*x;
}
 
const int maxn=1010;
int a,b,n;
int d[maxn][maxn];
int q[2][maxn],ll[2],rr[2];
int mx[maxn][maxn],mi[maxn][maxn];
int ans=1e9;
 
int main()
{
    a=read(); b=read(); n=read();
    for(int i=1;i<=a;++i)
    for(int j=1;j<=b;++j)
    d[i][j]=read();
     
    for(int j=1;j<=a;++j)
    {
        ll[0]=ll[1]=rr[0]=rr[1]=1; 
        q[0][1]=q[1][1]=0;
        for(int i=1;i<=b;++i)
        {
            while(ll[0]<rr[0]&&q[0][ll[0]]<i-n+1)++ll[0];
            while(ll[0]<rr[0]&&d[j][q[0][rr[0]-1]]>=d[j][i])--rr[0];
            q[0][rr[0]++]=i;
            mi[j][i]=d[j][q[0][ll[0]]];
             
            while(ll[1]<rr[1]&&q[1][ll[1]]<i-n+1)++ll[1];
            while(ll[1]<rr[1]&&d[j][q[1][rr[1]-1]]<=d[j][i])--rr[1];
            q[1][rr[1]++]=i;
            mx[j][i]=d[j][q[1][ll[1]]];
        }
    }
     
    for(int j=n;j<=b;++j)
    {
        ll[0]=ll[1]=rr[0]=rr[1]=1; 
        q[0][1]=q[1][1]=0;
        for(int i=1;i<=a;++i)
        {
            while(ll[0]<rr[0]&&q[0][ll[0]]<i-n+1)++ll[0];
            while(ll[0]<rr[0]&&mi[q[0][rr[0]-1]][j]>=mi[i][j])--rr[0];
            q[0][rr[0]++]=i;
             
            while(ll[1]<rr[1]&&q[1][ll[1]]<i-n+1)++ll[1];
            while(ll[1]<rr[1]&&mx[q[1][rr[1]-1]][j]<=mx[i][j])--rr[1];
            q[1][rr[1]++]=i;
            if(i>=n)ans=min(ans,mx[q[1][ll[1]]][j]-mi[q[0][ll[0]]][j]);
        }
    }
    printf("%d",ans);
    return 0;
}

洛谷P2219 [HAOI2007]修筑绿化带

时空限制 1000ms / 128MB

题目描述

为了增添公园的景致,现在需要在公园中修筑一个花坛,同时在画坛四周修建一片绿化带,让花坛被绿化带围起来。
如果把公园看成一个MN的矩形,那么花坛可以看成一个CD的矩形,绿化带和花坛一起可以看成一个AB的矩形。
如果将花园中的每一块土地的“肥沃度”定义为该块土地上每一个小块肥沃度之和,那么,
绿化带的肥沃度=A
B块的肥沃度-C*D块的肥沃度
为了使得绿化带的生长得旺盛,我们希望绿化带的肥沃度最大。

输入格式:

第一行有6个正整数M,N,A,B,C,D

接下来一个M*N的数字矩阵,其中矩阵的第i行j列元素为一个整数Xij,表示该花园的第i行第j列的土地“肥沃度”。

输出格式:

一个正整数,表示绿化带的最大肥沃程度。

说明

30%的数据,1<=M,N<=50
100%的数据,1<=M,N<=1000,1<=A<=M,1<=B<=N,1<=C<=A-2,1<=D<=B-2,1<=“肥沃度”<=100


题目分析

和上面那题大同小异
预处理每个C*D 和 AB 矩阵的分数和
单调队列求每个(A-C-1)*(B-D-1)大小矩阵中A
B矩阵的分数最大值
对每个以i,j为右下角的C*D 更新一次答案即可
注意绿化带是修建在花坛四周的,单调队列处理的矩阵大小要减一

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long lt;

int read()
{
    int f=1,x=0;
    char ss=getchar();
    while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
    while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
    return f*x;
}

const int maxn=2010;
int n,m,A,B,C,D;
int val[maxn][maxn],sum[maxn][maxn];
int f[maxn][maxn],g[maxn][maxn];
int q[maxn],ll,rr;
int mx[maxn][maxn],mx2[maxn][maxn];

int main()
{
    n=read();m=read();
    A=read();B=read();C=read();D=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)
    for(int j=1;j<=m;++j)
    sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+val[i][j];
    
    for(int i=1;i<=n;++i)
    for(int j=1;j<=m;++j)
    {
        if(i>=C&&j>=D) f[i][j]=sum[i][j]-sum[i-C][j]-sum[i][j-D]+sum[i-C][j-D];
        if(i>=A&&j>=B) g[i][j]=sum[i][j]-sum[i-A][j]-sum[i][j-B]+sum[i-A][j-B];
    }
    
    int lim=B-D-1;
    for(int i=1;i<=n+(A-C);++i)
    {
        ll=rr=1;
        for(int j=1;j<=m+(B-D);++j)
        {
            while(ll<rr&&j-q[ll]+1>lim) ll++;
            while(ll<rr&&g[i][j]>=g[i][q[rr-1]]) rr--;
            q[rr++]=j;
            if(j>=lim) mx[i][j]=g[i][q[ll]];
        }
    }
    
    lim=A-C-1;
    for(int j=1;j<=m+(B-D);++j)
    {
        ll=rr=1;
        for(int i=1;i<=n+(A-C);++i)
        {
            while(ll<rr&&i-q[ll]+1>lim) ll++;
            while(ll<rr&&mx[i][j]>=mx[q[rr-1]][j]) rr--;
            q[rr++]=i;
            if(i>=lim) mx2[i][j]=mx[q[ll]][j];
        }
    }
    
    int ans=0;
    for(int i=C;i<n;++i)
    for(int j=D;j<m;++j)
    ans=max(ans,mx2[i+(A-C)-1][j+(B-D)-1]-f[i][j]);
    
    printf("%d",ans);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip
综合小区管理系统管理系统按照操作主体分为管理员和用户。管理员的功能包括报修管理、车位管理、车位分配管理、出入管理、字典管理、房屋管理、物业费缴纳管理、公告管理、物业人员投诉管理、我的私信管理、物业人员管理、用户管理、管理员管理。用户的功能包括管理部门以及部门岗位信息,管理招聘信息,培训信息,薪资信息等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 综合小区管理系统管理系统可以提高综合小区管理系统信息管理问题的解决效率,优化综合小区管理系统信息处理流程,保证综合小区管理系统信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理公告,管理综合小区管理系统信息,包括出入管理,报修管理,报修管理,物业费缴纳等,可以管理操作员。 出入管理界面,管理员在出入管理界面中可以对界面中显示,可以对招聘信息的招聘状态进行查看,可以添加新的招聘信息等。报修管理界面,管理员在报修管理界面中查看奖罚种类信息,奖罚描述信息,新增奖惩信息等。车位管理界面,管理员在车位管理界面中新增。公告管理界面,管理员在公告管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值