zoukankan      html  css  js  c++  java
  • P2219 [HAOI2007]修筑绿化带

    我是题面

    这道题跟理想的正方形很像,不大明白蛤OI是怎么想的,一年出两道这么相近的题

    这道题有两个矩形,所以就有了两种做法(说是两种做法,其实只是维护的矩形不同)

    一种是维护大矩形,一种是维护小矩形,我这里采取了维护小矩形的方法

    先求出以((i,j))为左上角的大矩形和小矩形的权值和为多少,然后用单调队列维护以(i,j)为左上角的大矩形里能放得最小的小矩形是哪个,最后做差得答案即可

    下面是代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cctype>
    #define ll long long
    #define gc getchar
    #define maxn 1005
    using namespace std;
    
    inline ll read(){
        ll a=0;int f=0;char p=gc();
        while(!isdigit(p)){f|=p=='-';p=gc();}
        while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
        return f?-a:a;
    }int n,m,a,b,c,d,ans,w[maxn][maxn];
    int w1[maxn][maxn],w2[maxn][maxn],x[maxn][maxn],y[maxn][maxn];
    
    struct ahaha{
        int s,id;
    }q[maxn];int h,t;
    
    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)
                w[i][j]=w[i-1][j]+w[i][j-1]+read()-w[i-1][j-1];
        for(int i=1;i<=n-c+1;++i)
            for(int j=1;j<=m-d+1;++j){
                w1[i][j]=w[i+c-1][j+d-1]-w[i+c-1][j-1]-w[i-1][j+d-1]+w[i-1][j-1];
                if(i<=n-a+1&&j<=m-b+1)
                    w2[i][j]=w[i+a-1][j+b-1]-w[i+a-1][j-1]-w[i-1][j+b-1]+w[i-1][j-1];
            }
        for(int i=1;i<=n-c+1;++i){
            int l=b-d+1;
            for(int j=1;j<l;++j){
                while(h<=t&&w1[i][j]<=q[t].s)--t;
                q[++t]={w1[i][j],j};
            }
            for(int j=l;j<=m-d+1;++j){
                while(h<=t&&j-q[h].id>=l-1)++h;
                x[i][j-l+1]=q[h].s;
                while(h<=t&&w1[i][j]<=q[t].s)--t;
                q[++t]={w1[i][j],j};
            }
            h=1,t=0;
        }
        for(int i=1;i<=m-b+1;++i){
            int l=a-c+1;
            for(int j=1;j<l;++j){
                while(h<=t&&x[j][i]<=q[t].s)--t;
                q[++t]={x[j][i],j};
            }
            for(int j=l;j<=n-c+1;++j){
                while(h<=t&&j-q[h].id>=l-1)++h;
                y[j-l+1][i]=q[h].s;
                while(h<=t&&x[j][i]<=q[t].s)--t;
                q[++t]={x[j][i],j};
            }
            h=1,t=0;
        }
        for(int i=1;i<=n-a+1;++i)
            for(int j=1;j<=m-b+1;++j)
                ans=max(ans,w2[i][j]-y[i][j]);
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    用c#开发微信(2)扫描二维码,用户授权后获取用户基本信息 (源码下载)
    3分钟上手log4net
    sql server 小技巧(8) visual studio 2013里使用Sql server compact 4.0及发布问题处理
    用c#开发微信(1)服务号的服务器配置和企业号的回调模式
    Dynamic CRM 2015学习笔记(6)没有足够的权限
    STL
    表格视图
    表格视图
    STL
    Python编程-Office操作-操作Excel(中)
  • 原文地址:https://www.cnblogs.com/hanruyun/p/10282671.html
Copyright © 2011-2022 走看看