您的位置:首页 > 其它

【BOI2012】Peaks

2017-03-01 20:58 681 查看
Description

有一个居住在多山岛屿的登山家,已经攀上了一座山峰,并且要攀爬另外一座更高的山峰。

更精确地说,岛上的每一点都有一个大于零的海拔(海面的海拔为零),并且如果登山家位于海拔Ei的山峰上,那么他的目标是到达其他海拔为Ej(Ej>Ei)的山峰。因为登山家在一个山峰上,所以无法马上向上爬——为了到达一个海拔更高的地点,登山家需要先下山才能上山。下山的路不及上山精彩,因此,登山家想将从当前地点到达更高山峰途中最低点的海拔最大化。

岛屿的地图是一个二维的N*M的矩形网格,并且描述了岛屿每一部分的海拔——格子里的数字表示岛屿对应地区的海拔。如果两个各自有公共点,那么他们相邻。因此,每个格子(除了在边界上的)和其他8个格子相邻。一条路径是一系列的格子,序列中连续的两个格子相邻。一个“平区域”是一个相同海拔格子的集合,并且集合中任意两个格子能够用仅经过这个集合内格子的路径连接。任意两个等高的相邻格子属于同一“平区域” 。一座山峰,是一个相邻的格子中没有更高海拔的“平区域”。

写一个程序,找到所有山峰,并且计算每个山峰到达更高山峰路途中最大的最低海拔。对于岛上最高的山峰(岛上没有更高的山峰),可以确定登山家会离开岛屿寻找更高的山峰,因此,路途中的最低海拔为零(海平面的海拔)。

Input

输入的第一行包含两个整数N和M(1<=N,M<=2000,N*M<=10^5),分别是地图的高和宽。

接下来N行包含岛屿地图的描述。其中每行包含M个空格隔开的整数Eij(1<=Eij<=10^6)。格子Eij(对应地图的i 行j 列)的海拔为输入的i+1行第j 个整数。

Output

输出的第一行须包含一个整数P,岛屿中山峰的个数。接下来P行须每行包含两个整数:这座山峰的海拔及到达更高山峰途中最低点海拔的最大值。这些山峰的信息按照海拔降序输出;如果若干座山峰海拔相同,那么它们按照那个最低点的海拔降序输出。

Sample Input

输入1:

6 6

21 16 9 11 6 7

21 21 10 14 15 9

18 20 8 9 13 14

11 10 9 9 8 13

8 12 12 14 13 8

7 13 12 9 5 1

输入2:

5 3

16 14 16

14 14 15

12 17 16

12 13 10

16 11 16

Sample Output

输出1:

4

21 0

15 11

14 13

13 12

输出2:

5

17 0

16 15

16 14

16 13

16 13

Data Constraint

• 15 分的数据中N<=2或M<=2。

• 50 分的数据中有P<=500。

• 80 分的数据中有P<=5000。

题解

我们可以先把作为峰的合并为一个块,然后其他点每一个都作为一个块

然后按照高度由大到小插入块并且进行合并操作就可以了

但是这题细节很多所以说要耐心实现

var
stack,cc:array[0..100005]of longint;
father,big,bt:array[0..200005]of longint;
go:array[0..9]of longint;
a,ans:array[0..100005,1..2]of longint;
bz:array[0..400005]of boolean;
i,j,k,l,n,m,x,y,z,p,q,max1,max2,s:longint;
b:boolean;
procedure qsort(l,r:longint);
var
i,j,mid:longint;
begin
i:=l;
j:=r;
mid:=a[(i+j) div 2,1];
repeat
while a[i,1]>mid do inc(i);
while a[j,1]<mid do dec(j);
if i<=j then
begin
a[0]:=a[i];
a[i]:=a[j];
a[j]:=a[0];
inc(i);
dec(j);
end;
until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j);
end;
procedure qsort1(l,r:longint);
var
i,j,mid,midd:longint;
begin
i:=l;
j:=r;
mid:=ans[(i+j) div 2,1];
midd:=ans[(i+j) div 2,2];
repeat
while (ans[i,1]>mid) or ((ans[i,1]=mid) and (ans[i,2]>midd)) do inc(i);
while (ans[j,1]<mid) or ((ans[j,1]=mid) and (ans[j,2]<midd)) do dec(j);
if i<=j then
begin
ans[0]:=ans[i];
ans[i]:=ans[j];
ans[j]:=ans[0];
inc(i);
dec(j);
end;
until i>j;
if i<r then qsort1(i,r);
if l<j then qsort1(l,j);
end;
function getfather(x:longint):longint;
begin
if father[x]=x then exit(x) else
father[x]:=getfather(father[x]);
exit(father[x]);
end;
function check(x,y:longint):boolean;
begin
if (x-1) mod m=0 then
if (y=2) or (y=6) or (y=1) then exit(false);
if x mod m=0 then
if (y=4) or (y=5) or (y=8) then exit(false);
exit(true);
end;
begin
//assign(input,'t4.in'); reset(input);
assign(input,'peaks.in'); reset(input);
assign(output,'peaks.out'); rewrite(output);
readln(n,m);
for i:=1 to n do
begin
for j:=1 to m do
begin
inc(p);
read(a[p,1]);
a[p,2]:=p;
if a[p,1]>max1 then max1:=a[p,1];
cc[p]:=a[p,1];
end;
readln;
end;
go[1]:=-1; go[2]:=-m-1; go[3]:=-m; go[4]:=-m+1;
go[5]:=1; go[6]:=m-1; go[7]:=m; go[8]:=m+1;
qsort(1,p);
for i:=1 to 2*p do father[i]:=i;
j:=1;
for i:=max1 downto 1 do
begin
while (j>0) and (a[j,1]=i) do
begin
if bz[a[j,2]]=true then
begin
inc(j);
continue;
end;
b:=false;
stack[0]:=1; stack[1]:=a[j,2];
l:=0;
bz[a[j,2]]:=true;
while stack[0]>l do
begin
inc(l);
x:=stack[l];
for k:=1 to 8 do
if (go[k]+x>0) and (go[k]+x<=p) then
begin
if check(x,k)=false then continue;
y:=go[k]+x;
if cc[y]>cc[x] then b:=true;
if (cc[y]=cc[x]) and (bz[y]=false) then
begin
bz[y]:=true;
inc(stack[0]);
stack[stack[0]]:=y;
end;
end;
end;
if b=false then
begin
inc(q);
for k:=1 to stack[0] do
begin
father[stack[k]]:=q+p;
big[q+p]:=cc[stack[k]];
end;
end;
inc(j);
end;
end;
z:=0;
fillchar(bz,sizeof(bz),false);
for i:=1 to p do
begin
if a[i,1]=1742 then
begin
a[i,1]:=a[i,1];
end;
max2:=0;
for j:=0 to 8 do
if (a[i,2]+go[j]>0) and (a[i,2]+go[j]<=p) then
begin
if check(a[i,2],j)=false then continue;
if cc[a[i,2]]>cc[a[i,2]+go[j]] then continue;
y:=a[i,2]+go[j];
if big[getfather(y)]>=max2 then
begin
l:=getfather(y);
max2:=big[l];
if (cc[y]=max1) and (bz[l]=false) then
begin
bz[l]:=true;
inc(z);
ans[z,1]:=cc[y]; ans[z,2]:=0;
end;
end;
end;
y:=l;
for k:=0 to 8 do
if (a[i,2]+go[k]>0) and (a[i,2]+go[k]<=p) then
begin
if cc[a[i,2]]>cc[a[i,2]+go[k]] then continue;
if check(a[i,2],k)=false then continue;
x:=getfather(a[i,2]+go[k]);
if x<>y then
begin
if (bz[x]=false) and (x>p) and (big[x]<big[y]) then
begin
if a[i,1]=735 then
begin
a[i,1]:=a[i,1];
end;
bz[x]:=true;
for s:=z+1 to z+bt[x]+1 do
begin
ans[s,1]:=big[x];
ans[s,2]:=a[i,1];
end;
inc(z,bt[x]+1);
if a[i,1]=1742 then
begin
a[i,1]:=a[i,1];
end;
end else if big[x]=big[y] then
begin
inc(bt[y],bt[x]+1);
end;
father[x]:=y;
end;
end;
end;
qsort1(1,z);
writeln(z);
for i:=1 to z do writeln(ans[i,1],' ',ans[i,2]);
close(input); close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: