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.