洛谷 P2219修築綠化帶 二維單調隊列~

題目鏈接:https://www.luogu.org/problem/P2219

emmm調了一個上午+中午,fan

題意:從N*M的中找到一個a*b的大矩形和減去a*b中的一個與之不重邊界的c*d的小矩形和最大

 二維處理前綴和兩次,分別是處理出以i,j爲右下角的a*b矩形和A[i][j],以c*d矩形和B[i][j];

然後我們以B[i][j]的每一行行進行單調隊列維護一個j-b+d-2~j的最小值 P[i][j]

再以P[i][j]的每一列維護一個從i-a+c-2~i的單調隊列T[i][j]

因爲不重邊 所以ans=min(A[i][j]-T[i-1][j-1]) (i>=a&&j>=b)

OVER !但是我還是wa了一上午

因爲維護某個數長度k最小值的時候,前k個可能都是0,這個時候維護一個長度k+1的單調隊列就不會出現第一個應該取他本身但是誤取了0的錯誤算法 ~太笨了

十分可惜的代碼如下:

//#pragma comment (linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
#include<stdio.h>
#include<string.h>
#include<string>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<stack>
#include<vector>
#include<map>
#include<queue>
#include<list>
#include<time.h>
#include<bitset>

#define myself i,l,r
#define lson i<<1
#define rson i<<1|1
#define Lson i<<1,l,mid
#define Rson i<<1|1,mid+1,r
#define half (l+r)/2
#define lowbit(x) x&(-x)
#define min4(a, b, c, d) min(min(a,b),min(c,d))
#define min3(x, y, z) min(min(x,y),z)
#define max3(x, y, z) max(max(x,y),z)
#define max4(a, b, c, d) max(max(a,b),max(c,d))
#define pii make_pair
#define pr pair<int,int>
typedef unsigned long long ull;
typedef long long ll;
const int inff = 0x3f3f3f3f;
const long long inFF = 9223372036854775807;
const int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
const int mdir[8][2] = {0, 1, 0, -1, 1, 0, -1, 0, 1, 1, -1, 1, 1, -1, -1, -1};
const double eps = 1e-10;
const double PI = acos(-1.0);
const double E = 2.718281828459;
using namespace std;
const int mod=1e9+7;
const int maxn=1005;
int s[maxn][maxn],A[maxn][maxn],B[maxn][maxn];
int P[maxn][maxn],T[maxn][maxn];
int q[maxn];
int main()
{
    int n,m,a,b,c,d;
    cin>>n>>m>>a>>b>>c>>d;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&s[i][j]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
    for(int i=a;i<=n;i++)
        for(int j=b;j<=m;j++)
            A[i][j]=s[i][j]-s[i-a][j]-s[i][j-b]+s[i-a][j-b];//A表示大矩形和
    for(int i=c+1;i<n;i++)
        for(int j=d+1;j<m;j++)
            B[i][j]=s[i][j]-s[i-c][j]-s[i][j-d]+s[i-c][j-d];//小矩形和
//    for(int i=1;i<=n;i++)
//    {
//        for(int j=1;j<=m;j++)
//            cout<<A[i][j]<<" ";
//        cout<<endl;
//    }
//    cout<<endl;
//    for(int i=1;i<=n;i++)
//    {
//        for(int j=1;j<=m;j++)
//            cout<<B[i][j]<<" ";
//        cout<<endl;
//    }
//    cout<<endl;
    for(int i=c+1;i<n;i++)
    {
        int l=1,r=0;
        for(int j=d+1;j<m;j++)//P維護一段小矩形行的單調隊列,j位置維護 j-b+d+1~j-1,單調隊列區間長度爲b-d-2;
        {
            while(l<=r&&q[l]<j-b+d+2) l++;
            while(l<=r&&B[i][q[r]]>=B[i][j]) r--;
            q[++r]=j;
            P[i][j]=B[i][q[l]];
        }
    }
//    for(int i=1;i<=n;i++)
//    {
//        for(int j=1;j<=m;j++)
//            cout<<P[i][j]<<" ";
//        cout<<endl;
//    }
//    cout<<endl;
    for(int j=c+1;j<m;++j)
    {
        int l=1,r=0;
        for(int i=c+1;i<n;i++)
        {
            while(l<=r&&P[q[r]][j]>=P[i][j]) r--;
            q[++r]=i;
            while(l<=r&&q[l]<i-a+c+2) l++;
            T[i][j]=P[q[l]][j];
        }
    }
//    for(int i=1;i<=n;i++)
//    {
//        for(int j=1;j<=m;j++)
//            cout<<T[i][j]<<" ";
//        cout<<endl;
//    }
//    cout<<endl;
    int ans=0;
    for(int i=a;i<=n;i++)
        for(int j=b;j<=m;j++)
            ans=max(ans,A[i][j]-T[i-1][j-1]);
    cout<<ans<<endl;
}
/*
 4 5 4 4 1 1
 1 2 3 4 5
 6 7 8 9 10
 11 12 13 14 15
 16 17 18 19 20
 */

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章