poj1151 Atlantis

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

 

_______________________________________________

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

多组数据。

_______________________________________________

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

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

_______________________________________________

 

  1 Program Stone;
  2 
  3 var i,j,k,n,m,tot:longint;
  4 
  5     x1,y1,x2,y2:array[1..100]of real;
  6 
  7     s,p:array[0..200]of real;
  8 
  9     io:array[1..200]of longint;
 10 
 11     lc,rc,ans:real;
 12 
 13     b:array[1..1000]of longint;
 14 
 15     a:array[1..1000]of real;
 16 
 17  procedure kp(t,w:longint);
 18 
 19  var i,j,l:longint;
 20 
 21      k,mid:real;
 22 
 23   begin
 24 
 25     i:=t;j:=w;mid:=s[(t+w)div 2];
 26 
 27     repeat
 28 
 29       while s[i]<mid do inc(i);
 30 
 31       while s[j]>mid do dec(j);
 32 
 33       if i<=j then begin
 34 
 35                      k:=s[i];s[i]:=s[j];s[j]:=k;
 36 
 37                      l:=io[i];io[i]:=io[j];io[j]:=l;
 38 
 39                      inc(i);dec(j);
 40 
 41                    end;
 42 
 43     until i>j;
 44 
 45     if i<w then kp(i,w);
 46 
 47     if j>t then kp(t,j);
 48 
 49   end;
 50 
 51  procedure upadd(head,tail,num:longint);           //增加一条左边,即加入一个矩形。
 52 
 53  var i,j,k:longint;
 54 
 55   begin
 56 
 57     if (lc<=head)and(tail<=rc) then begin
 58 
 59                                       a[num]:=p[tail]-p[head-1];
 60 
 61                                       inc(b[num]);    //该区间被几个矩形覆盖。
 62 
 63                                       exit;
 64 
 65                                     end;
 66 
 67     k:=(head+tail)div 2;
 68 
 69     if lc<=k then upadd(head,k,num*2);
 70 
 71     if k<rc then upadd(k+1,tail,num*2+1);
 72 
 73     a[num]:=a[num*2]+a[num*2+1];                        //区间被覆盖长度为他的左右子区间被覆盖长度和。
 74 
 75     if b[num]>0 then a[num]:=p[tail]-p[head-1];         //若该区间被整段覆盖,这a[i]为区间长度。
 76 
 77   end;
 78 
 79  procedure updel(head,tail,num:longint);           //删除一个矩形。
 80 
 81  var i,j,k:longint;
 82 
 83   begin
 84 
 85     if (lc<=head)and(tail<=rc) then begin
 86 
 87                                       dec(b[num]);    //该区间被几个矩形覆盖。
 88 
 89                                       if b[num]=0 then a[num]:=a[num*2]+a[num*2+1];   //如果未被整段覆盖,区间被覆盖长度为他的左右子区间被覆盖长度和。
 90 
 91                                       exit;
 92 
 93                                     end;
 94 
 95     k:=(head+tail)div 2;
 96 
 97     if lc<=k then updel(head,k,num*2);
 98 
 99     if k<rc  then updel(k+1,tail,num*2+1);
100 
101     if b[num]=0 then a[num]:=a[num*2]+a[num*2+1];
102 
103   end;
104 
105  
106 
107  procedure init;
108 
109  var i,j,k:longint;
110 
111   begin
112 
113    readln(n);tot:=0;
114 
115    while n<>0 do
116 
117     begin
118 
119      inc(tot);
120 
121      for i:=1 to n do
122 
123       begin
124 
125         readln(x1[i],y1[i],x2[i],y2[i]);
126 
127         s[i]:=y1[i];s[i+n]:=y2[i];                 
128 
129         io[i]:=i;io[i+n]:=i+n;
130 
131       end;
132 
133      kp(1,2*n);
134 
135      m:=1;y1[io[1]]:=1;
136 
137      for i:=2 to 2*n do
138 
139       begin
140 
141        if s[i]<>s[i-1] then begin
142 
143                              p[m]:=s[i]-s[i-1];
144 
145                              inc(m);
146 
147                             end;
148 
149        if io[i]>n then y2[io[i]-n]:=m
150 
151                   else y1[io[i]]:=m; 
152 
153       end;                                                    //将纵坐标排序,离散化标号。
154 
155  
156 
157      for i:=2 to m do p[i]:=p[i]+p[i-1];                      //记录每个标号之间的实际距离。
158 
159      for i:=1 to n do
160 
161       begin
162 
163         s[i]:=x1[i];s[i+n]:=x2[i];
164 
165         io[i]:=i;io[i+n]:=i+n;
166 
167       end;
168 
169      kp(1,2*n);                                               //按横坐标排序,依次读入。
170 
171      ans:=0;
172 
173      for i:=1 to 2*n do
174 
175       begin
176 
177         if s[i]<>s[i-1] then ans:=ans+a[1]*(s[i]-s[i-1]);//将图割成一竖竖,如果是新的一竖,即将这一竖中被覆盖的面积加入答案。 
178 
179         if io[i]>n then j:=io[i]-n else j:=io[i];        //判断是左边还是右边。
180 
181         lc:=y1[j];rc:=y2[j]-1;                           //记录要修改的区间。
182 
183         if io[i]<=n  then upadd(1,m,1)                   //左右边分开处理,其实是可以合在一起做的。
184 
185                      else updel(1,m,1);
186 
187       end;
188 
189      writeln('Test case #',tot);
190 
191      writeln('Total explored area: ',ans:0:2);
192 
193      writeln;
194 
195      readln(n);
196 
197     end;
198 
199   end;
200 
201 begin
202 
203  assign(input,'input.in');reset(input);
204 
205  init;
206 
207  close(input);
208 
209 end.

 

posted on 2016-03-02 17:38  Yesphet  阅读(247)  评论(0编辑  收藏  举报