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;
}