wannafly19 矩阵
1 /* 2 Source :牛客网wannafly 19 矩阵 3 Problem :在一个n*m ,n,m<500的网格中,求满足条件的最大矩阵,行数<=X,列数<=Y,0的个数<=Z 4 Solution :枚举两列转换成一维的问题,然后用单调队列维护满足条件的最小值,那么最大值=当前值-最小值。 5 Date :2018-08-16-10.51 6 */ 7 8 #include <bits/stdc++.h> 9 using namespace std; 10 11 typedef long long LL; 12 const int MAXN = 100005; 13 const LL MOD7 = 1e9+7; 14 const LL INF = 1e18+9; 15 16 int a[505][505]; 17 LL sum[505][505]; // 一行的前缀和 18 LL zero[505][505]; // 一行的前缀0的个数 19 LL qs[505]; //对应枚举的i-j的前缀和 20 LL qz[505]; // 对应枚举的i-j的0的个数 21 int qq[505]; // 单调队列对应的下标的位置(单调递增队列) 22 int n,m; 23 int X,Y,Z; 24 25 void work() 26 { 27 LL ans=0; 28 for (int i=1;i<=m;++i) 29 { 30 for (int j=i;j<=m && j-i+1<=Y;++j) 31 { 32 int L=0,R=0; 33 qq[R++]=0; 34 for (int k=1;k<=n;++k) 35 { 36 qs[k] = qs[k-1] + sum[k][j] - sum[k][i-1]; 37 qz[k] = qz[k-1] + zero[k][j] - zero[k][i-1]; 38 while (L<R && (k-qq[L]>X || qz[k]-qz[qq[L]]>Z)) ++L; //长度大于X或0的个数大于Z 39 if (L<R) ans = max(ans, qs[k]-qs[qq[L]]); //如果队列中还有元素,那么当前位置符合要求 40 while (L<R && qs[k] <= qs[qq[R-1]]) --R; // 保证队列的单调性 41 qq[R++] = k; 42 } 43 } 44 } 45 printf("%lld\n",ans); 46 } 47 48 49 int main() 50 { 51 #ifndef ONLINE_JUDGE 52 freopen("test.txt","r",stdin); 53 #endif // ONLINE_JUDGE 54 while (scanf("%d%d",&n,&m)!=-1) 55 { 56 scanf("%d%d%d",&X,&Y,&Z); 57 for (int i=1;i<=n;++i) 58 { 59 for (int j=1;j<=m;++j) 60 { 61 scanf("%d",&a[i][j]); 62 sum[i][j] = sum[i][j-1] + a[i][j]; 63 zero[i][j] = zero[i][j-1] + (a[i][j]==0); 64 } 65 } 66 work(); 67 } 68 return 0; 69 }