zoukankan      html  css  js  c++  java
  • bzoj4165: 矩阵(堆+hash)

      求第k大用堆维护最值并出堆的时候扩展的经典题...

      因为只有正数,所以一个矩阵的权值肯定比它的任意子矩阵的权值大,那么一开始把所有满足条件的最小矩阵加进堆里,弹出的时候上下左右扩展一行加进堆,用hash判重即可

    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<queue>
    #define uint unsigned int
    #define ull unsigned long long
    using namespace std;
    const int maxn=1010, mod=10000019;
    struct poi{int x1, yy1, x2, y2; uint sum;};
    struct tjm{ull too; int pre;}e[2000010];
    priority_queue<poi>q;
    bool operator<(poi a, poi b){return a.sum>b.sum;}
    int n, m, mna, mnb, k, tot;
    int last[mod];
    uint mp[maxn][maxn];
    void read(uint &k)
    {
        int f=1; k=0; char c=getchar();
        while(c<'0' || c>'9') c=='-' && (f=-1), c=getchar();
        while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();
        k*=f;
    }
    inline void add(int x, ull y){e[++tot].too=y; e[tot].pre=last[x]; last[x]=tot;}
    inline int makehs(ull x)
    {
        int tmp=x%mod;
        for(int i=last[tmp];i;i=e[i].pre)
        if(e[i].too==x) return i;
        add(tmp, x);
        return tot;
    }
    inline int hs(ull x)
    {
        int tmp=x%mod;
        for(int i=last[tmp];i;i=e[i].pre)
        if(e[i].too==x) return i;
        return -1;
    }
    inline void update(int x1, int yy1, int x2, int y2)
    {
        ull tmp=0;
        tmp=tmp*2333+x1; tmp=tmp*2333+yy1; tmp=tmp*2333+x2; tmp=tmp*2333+y2;
        if(hs(tmp)!=-1) return;
        makehs(tmp);
        q.push((poi){x1, yy1, x2, y2, mp[x2][y2]-mp[x2][yy1-1]-mp[x1-1][y2]+mp[x1-1][yy1-1]});
    }
    int main()
    {
        scanf("%d%d%d%d%d", &n, &m, &mna, &mnb, &k);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                read(mp[i][j]), mp[i][j]+=mp[i-1][j]+mp[i][j-1]-mp[i-1][j-1];
        for(int i=mna;i<=n;i++)
            for(int j=mnb;j<=m;j++)
            {
                ull tmp=0;
                int x1=i-mna+1, yy1=j-mnb+1, x2=i, y2=j;
                tmp=tmp*2333+x1; tmp=tmp*2333+yy1; tmp=tmp*2333+x2; tmp=tmp*2333+y2;
                makehs(tmp);
                q.push((poi){x1, yy1, x2, y2, mp[x2][y2]-mp[x2][yy1-1]-mp[x1-1][y2]+mp[x1-1][yy1-1]});
            }
        for(int i=1;i<=k;i++)
        {
            if(q.empty()) return puts("-1"), 0;
            poi t=q.top(); q.pop();
            int x1=t.x1, yy1=t.yy1, x2=t.x2, y2=t.y2;
            if(x1>1) update(x1-1, yy1, x2, y2);
            if(yy1>1) update(x1, yy1-1, x2, y2);
            if(x2<n) update(x1, yy1, x2+1, y2);
            if(y2<m) update(x1, yy1, x2, y2+1);
            if(i==k) printf("%u
    ", t.sum);
        }
    }
    View Code
  • 相关阅读:
    订餐系统之微信点餐
    Alfred工具
    使用密码记录工具keepass来保存密码
    一步一步实战扩展 ASP.NET Route,实现小写 URL、个性化 URL
    提高性能,抛弃反射
    -串行化与反串行化
    JavaScript 命名空间
    .net SoapHeader验证
    [置顶] Android Sensor系统剖析(4.0)(下)
    VirtualBox虚拟机下Windows登录密码破解方法(阿里云推荐码:1WFZ0V,立享9折!)
  • 原文地址:https://www.cnblogs.com/Sakits/p/7998663.html
Copyright © 2011-2022 走看看