[map][堆]JZOJ 4754 矩阵

Description

 

Input

Output

 

Sample Input

输入1:
3 4 2 2 3
0 1 3 7
1 16 5 2
7 6 9 3

输入2:
7 7 3 4 13
5 5 7 8 6 8 5
8 4 6 6 3 4 2
8 0 9 2 3 4 7
8 5 4 5 3 9 8
0 3 0 6 0 3 8
9 7 1 8 8 9 4
7 8 4 5 7 6 1

Sample Output

输出1:
19

输出2:
58

 

Data Constraint

分析

我们可以用堆来维护所有的最小(指面积)矩阵

然后每次提出值最小的那个,对它进行扩张,将扩张后的的矩阵加入堆

提出k次即为答案

注意判重,可以用map

 

#pragma GCC optimize(2)
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
typedef pair<ii,ii> iiii;
const int N=1e3+10;
struct Rect {
    ll sum;
    int x1,y1,x2,y2;
    friend bool operator < (Rect a,Rect b) {
        return a.sum<b.sum;
    }
};
map<iiii,bool> M;
Rect a[2000010];
ll s[N][N];
int n,m,ma,mb,k,sz;

void Delete() {
    a[1]=a[sz];sz--;
    int x=1;
    while (x<sz) {
        if ((x<<1)<=sz) {
            if ((x<<1)+1<=sz)  {
                if (a[x]<a[x<<1]&&a[x]<a[(x<<1)+1]) break;
                if (a[x<<1]<a[(x<<1)+1]) swap(a[x],a[x<<1]),x=x<<1;
                else swap(a[x],a[(x<<1)+1]),x=(x<<1)+1;
            }
            else {
                if (a[x]<a[x<<1]) break;
                swap(a[x],a[x<<1]);x=x<<1;
            }
        }
        else break;
    }
}

void Insert(Rect x) {
    a[++sz]=x;
    int y=sz;
    while (y>0) {
        if (a[y]<a[y>>1]) {
            swap(a[y],a[y>>1]);
            y=y>>1;
        }
        else break;
    }
}

ll SUM(int x1,int y1,int x2,int y2) {
    return s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];
}

int main() {
    scanf("%d%d%d%d%d",&n,&m,&ma,&mb,&k);
    int i,j;
    for (i=1;i<=n;i++)
        for (j=1;j<=m;j++)
            scanf("%lld",&s[i][j]),s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
    for (i=1;i<=n-ma+1;i++)
        for (j=1;j<=m-mb+1;j++) Insert((Rect){SUM(i,j,i+ma-1,j+mb-1),i,j,i+ma-1,j+mb-1});

    while (k--) {
        Rect r=a[1],u;Delete();
        if (k==0) {
            printf("%lld\n",r.sum);
            return 0;
        }
        if (r.x2<n) {
            u=r;
            u.x2++;u.sum+=SUM(u.x2,u.y1,u.x2,u.y2);
            if (!M[make_pair(make_pair(u.x1,u.y1),make_pair(u.x2,u.y2))]) {
                M[make_pair(make_pair(u.x1,u.y1),make_pair(u.x2,u.y2))]=1;
                Insert(u);
            }
        }
        if (r.y2<m) {
            u=r;
            u.y2++;u.sum+=SUM(u.x1,u.y2,u.x2,u.y2);
            if (!M[make_pair(make_pair(u.x1,u.y1),make_pair(u.x2,u.y2))]) {
                M[make_pair(make_pair(u.x1,u.y1),make_pair(u.x2,u.y2))]=1;
                Insert(u);
            }
        }
    }
}
View Code

 

posted @ 2019-03-21 21:21  Vagari  阅读(180)  评论(0编辑  收藏  举报