JZOJ 4754.矩阵

( 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);
}
原文地址:https://www.cnblogs.com/leiyuanze/p/15132831.html