这是刘汝佳神牛《算法艺术与信息学竞赛》上有关堆的一道例题。主要思路如下:

维护一个堆,存储的是水位和高度一样的格子的高度。

1、首先把边缘点全部加到堆中

2、每次取堆中最小的一个,做一次Floodfill,如果被fill到的点比队首元素高度高,那么将这个点加入堆中,否则将该点的水位设置为队首元素的水位。

3、重复2,直到堆中没有元素。

4、最后,统计答案为每个点水位高度与实际高度的差值和。

CODE

  1 const
2 maxn=90000;
3 maxp=300;
4 ddx:array[1..4]of integer=(0,0,1,-1);
5 ddy:array[1..4]of integer=(1,-1,0,0);
6 type
7 rec=record
8 x,y,data:longint;
9 end;
10 var
11 i,j,m,n,ans :longint;
12 map,high :array[1..maxp,1..maxp]of longint;
13 v :array[1..maxp,1..maxp]of boolean;
14 heap_size :longint;
15 heap :array[1..maxn]of rec;
16 tmp :rec;
17
18 procedure down(i:longint);
19 var j:longint;tmp:rec;
20 begin
21 while (i<<1)<=heap_size do
22 begin
23 j:=i << 1;
24 if (heap[j].data>heap[j+1].data)and(j<heap_size)then inc(j);
25 if heap[j].data<heap[i].data then
26 begin
27 tmp:=heap[i];heap[i]:=heap[j];heap[j]:=tmp;
28 i:=j;
29 end else break;
30 end;
31 end;
32
33 procedure up(i:longint);
34 var j:longint;tmp:rec;
35 begin
36 while i>1 do
37 begin
38 j:=i >> 1;
39 if heap[j].data>heap[i].data then
40 begin
41 tmp:=heap[i];heap[i]:=heap[j];heap[j]:=tmp;
42 i:=j;
43 end else break;
44 end;
45 end;
46
47 procedure build_heap;
48 begin
49 for i:=(heap_size>>1)downto 1 do down(i);
50 end;
51
52 procedure floodfill(p:rec);
53 var x,y,h,t,i :longint;
54 seq :array[1..maxn]of rec;
55 begin
56 h:=0;t:=1;seq[1]:=p;
57 while h<t do
58 begin
59 inc(h);
60 x:=seq[h].x;y:=seq[h].y;
61 for i:=1 to 4 do
62 if (x+ddx[i]>0)and(y+ddy[i]>0)and(x+ddx[i]<=m)and(y+ddy[i]<=n)then
63 begin
64 if (not v[x+ddx[i],y+ddy[i]]) then
65 begin
66 v[x+ddx[i],y+ddy[i]]:=true;
67 if map[x+ddx[i],y+ddy[i]]<=high[x,y] then
68 begin
69 high[x+ddx[i],y+ddy[i]]:=high[x,y];
70 inc(t);seq[t].x:=x+ddx[i];
71 seq[t].y:=y+ddy[i];
72 seq[t].data:=map[x+ddx[i],y+ddy[i]];
73 end else
74 begin
75 inc(heap_size);
76 heap[heap_size].x:=x+ddx[i];heap[heap_size].y:=y+ddy[i];
77 heap[heap_size].data:=high[x+ddx[i],y+ddy[i]];
78 up(heap_size);
79 end;
80 end;
81 end;
82 end;
83 end;
84
85 begin
86 heap_size:=0;
87 readln(n,m);
88 for i:=1 to m do
89 for j:=1 to n do
90 begin
91 read(map[i,j]);
92 high[i,j]:=map[i,j];
93 end;
94 fillchar(v,sizeof(v),0);
95 for i:=1 to m do
96 begin
97 v[i,1]:=true;inc(heap_size);heap[heap_size].x:=i;heap[heap_size].y:=1;heap[heap_size].data:=map[i,1];
98 v[i,n]:=true;inc(heap_size);heap[heap_size].x:=i;heap[heap_size].y:=n;heap[heap_size].data:=map[i,n];
99 end;
100 for j:=2 to n-1 do
101 begin
102 v[1,j]:=true;inc(heap_size);heap[heap_size].x:=1;heap[heap_size].y:=j;heap[heap_size].data:=map[1,j];
103 v[m,j]:=true;inc(heap_size);heap[heap_size].x:=m;heap[heap_size].y:=j;heap[heap_size].data:=map[m,j];
104 end;
105 build_heap;
106 while heap_size>0 do
107 begin
108 floodfill(heap[1]);
109 tmp:=heap[1];heap[1]:=heap[heap_size];heap[heap_size]:=tmp;
110 dec(heap_size);
111 if heap_size>0 then down(1);
112 end;
113 ans:=0;
114 for i:=1 to m do for j:=1 to n do inc(ans,high[i,j]-map[i,j]);
115 writeln(ans);
116 end.