1. 程式人生 > >bzoj4165: 矩陣(堆+hash)

bzoj4165: 矩陣(堆+hash)

spl getch top urn sed puts opened -m ||

  求第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\n", t.sum); } }
View Code

bzoj4165: 矩陣(堆+hash)