( ext{Problem})
( ext{Solution})
纪念我考场正解被二分暴力暴踩。。。
首先二分的话,显然可以二分出答案,然后数矩阵和大于等于本矩阵的是否有 (k) 个
加一些优化就可以 (AC)?!!
不管它,正解就是让矩阵行列大小从小到大扩展,矩阵和小一些的肯定已经出来了
做 (k) 次即可,注意判重
本人手打哈希表+手打堆,因为数组开小光荣 ( ext{RE} 80pts)
欲哭无泪
( ext{Code})
#include <cstdio>
#include <iostream>
#define LL long long
#define re register
#define register
using namespace std;
const int N = 1005, mod = 1e6 + 7;
int n, m, ma, mb, k, a[N][N];
LL s[N][N];
inline void read(int &x)
{
x = 0; char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
}
struct Hash{int x, y, nxt;}e[mod * 2 + 5];
int ht[mod + 5], tot;
inline void insert(int x, int y)
{
int key = (10000000LL * x + y) % mod;
e[++tot] = Hash{x, y, ht[key]}, ht[key] = tot;
}
inline int query(int x, int y)
{
int key = (10000000LL * x + y) % mod;
for(re int i = ht[key]; i; i = e[i].nxt)
if (e[i].x == x && e[i].y == y) return 1;
return 0;
}
struct node{int x0, y0, x1, y1; LL s;};
struct Heap{
int size;
node h[N * N * 2];
inline int check(int x, int y)
{
if (x > 0 && y > 0 && x <= n && y <= m) return 1;
return 0;
}
inline int Num(int x, int y){return (x - 1) * m + y;}
inline node top(){return h[1];}
inline void pop(){h[1] = h[size--], down(1);}
inline void up(int x){while (x > 1 && h[x].s < h[x >> 1].s) swap(h[x], h[x >> 1]), x >>= 1;}
inline void down(int x)
{
while (((x << 1) <= size && h[x].s > h[x << 1].s) || ((x << 1 | 1) <= size && h[x].s > h[x << 1 | 1].s))
{
int y = x << 1;
if (h[y | 1].s < h[y].s) y |= 1;
swap(h[x], h[y]), x = y;
}
}
inline void push(node c)
{
if (!(check(c.x0, c.y0) && check(c.x1, c.y1))) return;
if (query(Num(c.x0, c.y0), Num(c.x1, c.y1))) return;
insert(Num(c.x0, c.y0), Num(c.x1, c.y1));
c.s = s[c.x1][c.y1] - s[c.x0 - 1][c.y1] - s[c.x1][c.y0 - 1] + s[c.x0 - 1][c.y0 - 1];
h[++size] = c;
up(size);
}
}T;
int main()
{
read(n), read(m), read(ma), read(mb), read(k);
for(re int i = 1; i <= n; i++)
for(re int j = 1; j <= m; j++)
read(a[i][j]), s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
for(re int i = 1; i <= n - ma + 1; i++)
for(re int j = 1; j <= m - mb + 1; j++) T.push(node{i, j, i + ma - 1, j + mb - 1});
LL ans = -1; node now;
for(re int i = 1; i <= k; i++)
{
now = T.top(), T.pop();
if (i == k){ans = now.s; break;}
T.push(node{now.x0, now.y0, now.x1, now.y1 + 1});
T.push(node{now.x0, now.y0, now.x1 + 1, now.y1});
}
printf("%lld
", ans);
}