题目大意
求出一个n*m的矩阵中长至少为x宽至少为y的矩形价值的第K小。
每个元素都是非负整数,一个矩形的价值定义为所有元素和,相同价值的不同矩形在计算答案时算多个。
经典套路
观察一个以(x1,y1)为左上角的矩形。
假如右下角为(x2,y2),这个矩形一定比(x1,y1,x2+1,y2)和(x1,y1,x2,y2+1)都小。
所以先把所有位置为左上角的长为x宽为y的矩形扔进堆里。
每次取出一个矩形,然后将其往下和往右拓展一格的矩形扔进堆里。
我们这样可能拓展到同样的矩形,因此用map判重。
做k次即可。
#include<cstdio>
#include<algorithm>
#include<map>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
typedef pair<pi,pi> pii;
const int maxn=1000+10,maxtot=2000000+10;
struct dong{
int x1,y1,x2,y2;
ll data;
friend bool operator <(dong a,dong b){
return a.data<b.data;
}
};
map<pii,bool> bz;
ll sum[maxn][maxn],a[maxn][maxn],cnt;
dong heap[maxtot],zlt;
int i,j,k,l,t,n,m,x,y,x1,y1,x2,y2,p,tot;
ll getsum(int x1,int y1,int x2,int y2){
return sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1];
}
void put(dong x){
heap[++tot]=x;
int i=tot;
while (i>1&&heap[i]<heap[i/2]){
swap(heap[i],heap[i/2]);
i/=2;
}
}
void deletemin(){
heap[1]=heap[tot];
tot--;
int i=1,j;
while (i*2<=tot){
if (i*2+1>tot||heap[i*2]<heap[i*2+1]) j=i*2;else j=i*2+1;
if (heap[j]<heap[i]){
swap(heap[i],heap[j]);
i=j;
}
else break;
}
}
bool pd(){
int i,j,k,l;
cnt=0;
fo(i,1,n-x+1)
fo(j,1,m-y+1)
fo(k,x,n-i+1)
fo(l,y,m-j+1){
cnt++;
if (cnt==p) return 1;
}
return 0;
}
bool dp(int x1,int y1,int x2,int y2){
if (bz[make_pair(make_pair(x1,y1),make_pair(x2,y2))]) return 1;
bz[make_pair(make_pair(x1,y1),make_pair(x2,y2))]=1;
}
int main(){
scanf("%d%d%d%d%d",&n,&m,&x,&y,&p);
fo(i,1,n)
fo(j,1,m)
scanf("%lld",&a[i][j]);
fo(i,1,n)
fo(j,1,m)
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
if (!pd()){
printf("-1\n");
return 0;
}
fo(i,1,n-x+1)
fo(j,1,m-y+1){
zlt.x1=i;
zlt.y1=j;
zlt.x2=i+x-1;
zlt.y2=j+y-1;
bz[make_pair(make_pair(x1,y1),make_pair(x2,y2))]=1;
zlt.data=getsum(i,j,i+x-1,j+y-1);
put(zlt);
}
p--;
while (p--){
zlt=heap[1];
deletemin();
x1=zlt.x1;y1=zlt.y1;
x2=zlt.x2;y2=zlt.y2;
if (x2<n&&!dp(x1,y1,x2+1,y2)){
zlt.x2++;
zlt.data=getsum(x1,y1,x2+1,y2);
put(zlt);
zlt.x2--;
}
if (y2<m&&!dp(x1,y1,x2,y2+1)){
zlt.y2++;
zlt.data=getsum(x1,y1,x2,y2+1);
put(zlt);
}
}
zlt=heap[1];
printf("%lld\n",zlt.data);
}