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;
    }
    
  • 相关阅读:
    html5 本地存储
    javascript 中的 this 关键字详解
    重绘和回流
    javascript 的预解释机制
    zepto.js 实现原理解析
    python3.6新特性
    python面试终极准备
    科大讯飞语音合成api
    智能儿童玩具
    MySQL与MongoDB
  • 原文地址:https://www.cnblogs.com/hanruyun/p/10282671.html
Copyright © 2011-2022 走看看