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 }