您的位置:首页 > 其它

poj1151 Atlantis

2016-03-02 17:38 148 查看
Atlantis

Time Limit: 1000MSMemory Limit: 10000K

Total Submissions: 10563Accepted: 4146

Description

There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the island. But unfortunately, these maps describe different regions of Atlantis. Your friend Bill has to know the total area for which maps exist. You (unwisely) volunteered to write a program that calculates this quantity.

Input

The input consists of several test cases. Each test case starts with a line containing a single integer n (1 <= n <= 100) of available maps. The n following lines describe one map each. Each of these lines contains four numbers x1;y1;x2;y2 (0 <= x1 < x2 <= 100000;0 <= y1 < y2 <= 100000), not necessarily integers. The values (x1; y1) and (x2;y2) are the coordinates of the top-left resp. bottom-right corner of the mapped area.

The input file is terminated by a line containing a single 0. Don't process it.

Output

For each test case, your program should output one section. The first line of each section must be "Test case #k", where k is the number of the test case (starting with 1). The second one must be "Total explored area: a", where a is the total explored area (i.e. the area of the union of all rectangles in this test case), printed exact to two digits to the right of the decimal point.

Output a blank line after each test case.

Sample Input

2

10 10 20 20

15 15 25 25.5

0

Sample Output

Test case #1

Total explored area: 180.00

Source

Mid-Central European Regional Contest 2000

_______________________________________________

在一张地图内,给定许多矩形的左上角和右下角坐标,求最后所有矩形的面积并。

多组数据。

_______________________________________________

需要离散化处理。先将横坐标拉成线性,然后排序,将整张图割成一竖一竖的。因为坐标是实型,所以需要离散化处理将纵坐标排序重新标号,记录每两个标号之间的实际距离。

然后把每个矩形的纵方向边按从小到大依次处理。如果是矩形左边,即将矩形加入线段树,如果是右边,就删除该矩形。

_______________________________________________

Program Stone;

var i,j,k,n,m,tot:longint;

x1,y1,x2,y2:array[1..100]of real;

s,p:array[0..200]of real;

io:array[1..200]of longint;

lc,rc,ans:real;

b:array[1..1000]of longint;

a:array[1..1000]of real;

procedure kp(t,w:longint);

var i,j,l:longint;

k,mid:real;

begin

i:=t;j:=w;mid:=s[(t+w)div 2];

repeat

while s[i]<mid do inc(i);

while s[j]>mid do dec(j);

if i<=j then begin

k:=s[i];s[i]:=s[j];s[j]:=k;

l:=io[i];io[i]:=io[j];io[j]:=l;

inc(i);dec(j);

end;

until i>j;

if i<w then kp(i,w);

if j>t then kp(t,j);

end;

procedure upadd(head,tail,num:longint);           //增加一条左边,即加入一个矩形。

var i,j,k:longint;

begin

if (lc<=head)and(tail<=rc) then begin

a[num]:=p[tail]-p[head-1];

inc(b[num]);    //该区间被几个矩形覆盖。

exit;

end;

k:=(head+tail)div 2;

if lc<=k then upadd(head,k,num*2);

if k<rc then upadd(k+1,tail,num*2+1);

a[num]:=a[num*2]+a[num*2+1];                        //区间被覆盖长度为他的左右子区间被覆盖长度和。

if b[num]>0 then a[num]:=p[tail]-p[head-1];         //若该区间被整段覆盖,这a[i]为区间长度。

end;

procedure updel(head,tail,num:longint);           //删除一个矩形。

var i,j,k:longint;

begin

if (lc<=head)and(tail<=rc) then begin

dec(b[num]);    //该区间被几个矩形覆盖。

if b[num]=0 then a[num]:=a[num*2]+a[num*2+1];   //如果未被整段覆盖,区间被覆盖长度为他的左右子区间被覆盖长度和。

exit;

end;

k:=(head+tail)div 2;

if lc<=k then updel(head,k,num*2);

if k<rc  then updel(k+1,tail,num*2+1);

if b[num]=0 then a[num]:=a[num*2]+a[num*2+1];

end;

procedure init;

var i,j,k:longint;

begin

readln(n);tot:=0;

while n<>0 do

begin

inc(tot);

for i:=1 to n do

begin

readln(x1[i],y1[i],x2[i],y2[i]);

s[i]:=y1[i];s[i+n]:=y2[i];

io[i]:=i;io[i+n]:=i+n;

end;

kp(1,2*n);

m:=1;y1[io[1]]:=1;

for i:=2 to 2*n do

begin

if s[i]<>s[i-1] then begin

p[m]:=s[i]-s[i-1];

inc(m);

end;

if io[i]>n then y2[io[i]-n]:=m

else y1[io[i]]:=m;

end;                                                    //将纵坐标排序,离散化标号。

for i:=2 to m do p[i]:=p[i]+p[i-1];                      //记录每个标号之间的实际距离。

for i:=1 to n do

begin

s[i]:=x1[i];s[i+n]:=x2[i];

io[i]:=i;io[i+n]:=i+n;

end;

kp(1,2*n);                                               //按横坐标排序,依次读入。

ans:=0;

for i:=1 to 2*n do

begin

if s[i]<>s[i-1] then ans:=ans+a[1]*(s[i]-s[i-1]);//将图割成一竖竖,如果是新的一竖,即将这一竖中被覆盖的面积加入答案。

if io[i]>n then j:=io[i]-n else j:=io[i];        //判断是左边还是右边。

lc:=y1[j];rc:=y2[j]-1;                           //记录要修改的区间。

if io[i]<=n  then upadd(1,m,1)                   //左右边分开处理,其实是可以合在一起做的。

else updel(1,m,1);

end;

writeln('Test case #',tot);

writeln('Total explored area: ',ans:0:2);

writeln;

readln(n);

end;

end;

begin

assign(input,'input.in');reset(input);

init;

close(input);

end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: