解题报告 poj 2528 (罕见的浮水法解这个题的。。。。。。)

题目大意:给你若干个线段,按层次叠放,求全放好之后有多少线段可以露出来。

 

都说是线段树,可为啥我怎么看怎么是浮水捏?

PS:这个,本人交了 n 次,全超时/WA。。。。。。最后还是看别人的代码之后才改对的。。。。

这里先介绍一下浮水法

 

首先,联想一下,这无数条线段是竖直方向罗列的,也就是这样:

然后,将最下面的那个向上挪,挪到一定程度显然会遇到阻拦,然后,将他被阻拦的部分剪去。

这样一来,最后,这条线段如果浮到了最上面,也就是上面那一堆都没有挡住它,就将颜色记录上(此处记录的长度,我也不知道单纯 inc 一开始为什么过不去。。。⊙﹏⊙b汗)

 

所以,在这个基础上,再加个离散化,OK。。。。

 

额,其实离散化没那么恐怖,就是让每一个坐标都对应一个数值,可能你不知不觉中已经用过了。。。。

 

代码 SueMiller

program ACRush;
var ans,x,y:array[0..10001]of longint;
n:longint;
i,j,k,ca,cas,sum:longint;

procedure cover(l,r,k,c:longint);
begin
while ((k<n) and ((r<x[k]) or (l>y[k]))) do
inc(k);    //挡不住的,跳过,反正它也影响不了什么。。。不然超时。
if k>=n then begin
inc(ans[c],r-l+1);
exit;
end;

if l<x[k] then begin
cover(l,x[k]-1,k+1,c);
l:=x[k];
end;
if r>y[k] then begin
cover(y[k]+1,r,k+1,c);
r:=y[k];
end;   //剪啊剪
end;

begin
readln(cas);
for ca:=1 to cas do
begin
sum:=0;
fillchar(ans,sizeof(ans),0);
readln(n);
for i:=0 to n-1 do
readln(x[i],y[i]);

for i:=n-1 downto 0 do
begin
cover(x[i],y[i],i+1,i);
end;

for i:=0 to n-1 do
begin
if ans[i]>0 then inc(sum);
end;

writeln(sum);
end;
end.

posted @ 2011-12-27 15:40  木小漾  阅读(573)  评论(0编辑  收藏  举报