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 }

 

posted @ 2018-08-16 11:51  LeeSongt  阅读(123)  评论(0编辑  收藏  举报