jzoj 4754. 【GDOI2017模拟9.4】矩阵

question

题目全都是图片,就不贴了
这题一开始没有思路,后来看了看题解,想了想正解,随后似乎感觉这道题真得很简单。。。

solution

正解:堆

我们可以先将(n-mina+1)*(m-minb+1)个 Mina * Minb 的矩阵以及它的权值存进堆中。
而后取k-1次,对于第i次取 [i ~ j , k ~ l] 的矩阵,我们就将矩阵 [i ~ j+1, k ~ l] 以及 **[i ~ j,k ~ l+1]**存进堆中。最后输出即可。

但我们发现可能会有重复的矩阵出现,对于这些矩阵,我们就要特判掉。

而我比较蒟蒻,当时竟然没有想到哈希判重,就打了个优化暴力判重,结果跑了个第一 275ms

Code

#include<cstdio>
#include<algorithm>
#define N 1010
using namespace std;
struct node
{
	int up,down,le,ri;
	bool operator == (node x)
	{
		return up==x.up && down==x.down && le==x.le && ri==x.ri;
	}
}d[3000010],t,same[3000010];
int n,m,mina,minb,K,a[N][N];
long long value[3000010],value_now=0,val;
long long tot=0,total=0;
long long qz[N][N];

inline int read()
{
	int x=0; char c=getchar();
	while (c<'0' || c>'9') c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x;
}

void up(int x)
{
	while (x>1 && value[x]<value[x>>1])
		swap(value[x],value[x>>1]),swap(d[x],d[x>>1]),x>>=1;
}

void down()
{
	int x=1;long long t=2;
	if (t<tot && value[t]>value[t+1]) t++;
	while (t<=tot && value[t]<value[x])
	{
		swap(value[x],value[t]),swap(d[x],d[t]);
		x=t,t=x<<1;
		if (t<tot && value[t]>value[t+1]) t++; 
	}
}

bool check(node x)
{
	for (int i=1;i<=total;i++)
		if (same[i]==x) return 1;
	return 0;
}

int main()
{
	n=read(),m=read(),mina=read(),minb=read(),K=read()-1;
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
			a[i][j]=read(),qz[i][j]=qz[i-1][j]+qz[i][j-1]-qz[i-1][j-1]+a[i][j];
	for (int i=mina;i<=n;i++)
		for (int j=minb;j<=m;j++)
		{
			value[++tot]=qz[i][j]-qz[i][j-minb]-qz[i-mina][j]+qz[i-mina][j-minb];
			d[tot]=(node){i-mina+1,i,j-minb+1,j};up(tot);
		}
	while (K--)
	{
		while (value[1]==value_now && check(d[1]))
			d[1]=d[tot],value[1]=value[tot],tot--,down();
		if (value[1]>value_now) value_now=value[1],total=0;
		same[++total]=d[1];
//		printf("%d
",value[1]);
//		printf("%d %d %d %d
",d[1].up,d[1].down,d[1].le,d[1].ri);
		t=d[1],val=value[1];
		d[1]=d[tot],value[1]=value[tot],tot--;down();
		if (t.down<n)
		{
			value[++tot]=val+qz[t.down+1][t.ri]-qz[t.down+1][t.le-1]-qz[t.down][t.ri]+qz[t.down][t.le-1];
			d[tot]=t,d[tot].down++,up(tot);
		}
		if (t.ri<m)
		{
			value[++tot]=val+qz[t.down][t.ri+1]-qz[t.down][t.ri]-qz[t.up-1][t.ri+1]+qz[t.up-1][t.ri];
			d[tot]=t,d[tot].ri++,up(tot);
		}
		down();
	}
	while (value[1]==value_now && check(d[1]))
		d[1]=d[tot],value[1]=value[tot],tot--,down();
	printf("%lld
",value[1]);
	return 0;
}
转载需注明出处。
原文地址:https://www.cnblogs.com/jz929/p/11817552.html