NC17070 矩阵(前缀和+单调队列)
最大子矩阵和问题,一般都是用前缀和先计算行,然后枚举行,在列方向做单调队列
这样的复杂度是N^3,对于几百的数据足够了
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<map> #include<string> using namespace std; typedef long long ll; const int N=2e5+5; const int mod=19260817; ll g[505]; ll a[505][505]; ll zero[505][505]; int q[N]; ll tmp[505]; int main(){ int r,c; int x,y,z; cin>>r>>c>>x>>y>>z; int i,j; for(i=1;i<=r;i++){ for(j=1;j<=c;j++){ scanf("%lld",&a[i][j]); if(a[i][j]==0){ zero[i][j]=zero[i-1][j]+1; } else{ zero[i][j]=zero[i-1][j]; } a[i][j]+=a[i-1][j]; } } ll ans=0; int k; for(i=1;i<=r;i++){ for(j=i;j<i+x&&j<=r;j++){ int hh=0,tt=0; q[0]=0; memset(g,0,sizeof g); memset(tmp,0,sizeof tmp); for(k=1;k<=c;k++){ g[k]=a[j][k]-a[i-1][k]+g[k-1]; tmp[k]=zero[j][k]-zero[i-1][k]+tmp[k-1]; while(hh<=tt&&(tmp[k]-tmp[q[hh]]>z||k-q[hh]>y)) hh++; if(hh<=tt) ans=max(ans,g[k]-g[q[hh]]); while(hh<=tt&&g[q[tt]]>=g[k]) tt--; q[++tt]=k; } } } cout<<ans<<endl; return 0; }
没有人不辛苦,只有人不喊疼