[POJ2227]Wedding Juicer
题目大意:一个俯视图面积M*N的不规则立方体,给出二维上每格的高度,从上方向中间洒水,最后能积累多少单位体积水?
题解:LRJ黑书
积水的过程可看作是每格都有一个上界,取决于周边高度最小值。
而上界是可以传递向四方的。
所以每次取出一个最小的上界,计入答案后向四周推广。
初始化所有格子上界INF,边界上界0(无法积水),推广时推广max(上界,格子高度)
代码挫爆了
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define N 311
#define M 91000
const int INF =~0U>>1;
int ins[N][N],tab[M][2],b[N][N],pos[N][N];
void heapify(int s,int e){
int k,t0=tab[s][0],t1=tab[s][1],t;
t=b[t0][t1];
while((s<<1)<e){
if(b[tab[s<<1][0]][tab[s<<1][1]]<b[tab[(s<<1)+1][0]][tab[(s<<1)+1][1]]) k=s<<1;
else k=(s<<1)+1;
if(b[tab[k][0]][tab[k][1]]>=t) break;
tab[s][0]=tab[k][0];
tab[s][1]=tab[k][1];
pos[tab[s][0]][tab[s][1]]=s;
s=k;
}
if((s<<1)==e && b[tab[e][0]][tab[e][1]]<b[tab[s][0]][tab[s][1]]){
tab[s][0]=tab[e][0];
tab[s][1]=tab[e][1];
pos[tab[s][0]][tab[s][1]]=s;
s=e;
}
tab[s][0]=t0;
tab[s][1]=t1;
pos[t0][t1]=s;
}
void heap(int s){
int t0=tab[s][0],t1=tab[s][1],tt=b[t0][t1],k;
while(s>1 && b[tab[s>>1][0]][tab[s>>1][1]]>tt){
tab[s][0]=tab[s>>1][0];
tab[s][1]=tab[s>>1][1];
pos[tab[s][0]][tab[s][1]]=s;
s>>=1;
}
tab[s][0]=t0;
tab[s][1]=t1;
pos[t0][t1]=s;
}
int main(){
int n,m,i,j,u,v,t,res;
scanf("%d%d",&m,&n);
for(i=1;i<=n;i++) for(j=1;j<=m;j++) scanf("%d",&ins[i][j]);
t=res=0;
for(i=1;i<=n;i++) for(j=1;j<=m;j++){
tab[++t][0]=i;
tab[t][1]=j;
pos[i][j]=t;
b[i][j]=INF;
}
for(i=0;i<=n+1;i++) pos[i][0]=pos[i][m+1]=t+1;
for(i=0;i<=m+1;i++) pos[0][i]=pos[n+1][i]=t+1;
for(i=1;i<=n;i++) b[i][1]=b[i][m]=0;
for(i=1;i<=m;i++) b[1][i]=b[n][i]=0;
for(i=t>>1;i>0;i--) heapify(i,t);
while(t){
u=tab[1][0];v=tab[1][1];
if(b[u][v]>ins[u][v]) res+=b[u][v]-ins[u][v];
i=max(b[u][v],ins[u][v]);
if(b[u+1][v]>i){
b[u+1][v]=i;
heap(pos[u+1][v]);
}
if(b[u][v+1]>i){
b[u][v+1]=i;
heap(pos[u][v+1]);
}
if(b[u-1][v]>i){
b[u-1][v]=i;
heap(pos[u-1][v]);
}
if(b[u][v-1]>i){
b[u][v-1]=i;
heap(pos[u][v-1]);
}
tab[1][0]=tab[t][0];
tab[1][1]=tab[t][1];
heapify(1,--t);
}
printf("%d\n",res);
return 0;
}