POJ·1151 Atlantis·线段树求矩形面积并

题目在这:http://poj.org/problem?id=1151

Atlantis

Time Limit: 1000MS   Memory Limit: 10000K

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

还是比较裸的线段树求矩形面积并,与上一题基本相同,不同的是这题坐标是小数,需要离散。

离散的时候学习了一个函数:unique函数,功能是将数组相邻的重复元素放到最后面,返回最后面的地址。

用的时候需要对数组进行排序,长度 = unique(name,name+len) - name - 1

codes:

 1 #include<set>
 2 #include<queue>
 3 #include<vector>
 4 #include<cstdio>
 5 #include<cstdlib>
 6 #include<cstring>
 7 #include<iostream>
 8 #include<algorithm>
 9 using namespace std;
10 const int N = 110;
11 #define Ch1 (i<<1)
12 #define Ch2 (Ch1|1)
13 #define mid(i) T[i].mid
14 #define len(i) T[i].r - T[i].l
15 #define rlen(i) T[i].rr - T[i].rl
16 #define For(i,n) for(int i=1;i<=n;i++)
17 #define Rep(i,l,r) for(int i=l;i<=r;i++)
18
19 struct tnode{
20     int l,r,mid,cover;
21     double rl,rr,len;
22 }T[N<<8];
23
24 struct lines{
25     double l,r,h;
26     int kind;//1表示上底边
27 }L[N*2];
28 int n,Lim,tot,kth;
29 double x1,y1,x2,y2,cor[N*2],ans;
30
31 bool cmp(lines A,lines B){
32     return A.h<B.h;
33 }
34
35 void init(){
36     tot = 0;ans = 0;
37     For(i,n){
38         scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
39         L[++tot].l = x1; L[tot].r = x2; L[tot].h = y1; L[tot].kind = 0; cor[tot] = x1;
40         L[++tot].l = x1; L[tot].r = x2; L[tot].h = y2; L[tot].kind = 1; cor[tot] = x2;
41     }
42     sort(L+1,L+tot+1,cmp);
43     sort(cor+1,cor+tot+1);
44     Lim = unique(cor+1,cor+tot+1) - cor - 1;
45 }
46
47 void Build(int l,int r,int i){
48     T[i].l = l; T[i].r = r; T[i].mid = (l+r)>>1;
49     T[i].rl = cor[l]; T[i].rr = cor[r];
50     if(l==r-1) return;
51     Build(l,mid(i),Ch1); Build(mid(i),r,Ch2);
52 }
53
54 void Modify(int i,double l,double r,int delta){
55     if(l==T[i].rl&&T[i].rr==r){
56         T[i].cover+=delta;
57         if(T[i].cover>0)        T[i].len = rlen(i);else
58         if(T[i].l+1==T[i].r)    T[i].len = 0;      else
59                                 T[i].len = T[Ch1].len + T[Ch2].len;
60         return;
61     }
62     double Mid = cor[mid(i)];
63     if(r<=Mid)  Modify(Ch1,l,r,delta);else
64     if(l>=Mid)  Modify(Ch2,l,r,delta);else
65     Modify(Ch1,l,Mid,delta),Modify(Ch2,Mid,r,delta);
66     if(T[i].cover>0)            T[i].len = rlen(i);
67     else                        T[i].len = T[Ch1].len + T[Ch2].len;
68 }
69
70 int main(){
71     scanf("%d",&n);
72     while(n){
73         init();kth++;
74         Build(1,Lim,1);L[0].h = L[1].h;
75         For(i,tot){
76             if(!L[i].kind){
77                 ans+=T[1].len * (L[i].h - L[i-1].h);
78                 Modify(1,L[i].l,L[i].r,1);
79             }else{
80                 ans+=T[1].len * (L[i].h - L[i-1].h);
81                 Modify(1,L[i].l,L[i].r,-1);
82             }
83         }
84         printf("Test case #%d\n",kth);
85         printf("Total explored area: %.2f\n",ans);
86         printf("\n");
87         scanf("%d",&n);
88         if(!n) return 0;
89     }
90     return 0;
91 }

POJ·1151 Atlantis·线段树求矩形面积并

时间: 2024-10-17 21:50:05

POJ·1151 Atlantis·线段树求矩形面积并的相关文章

POJ 1151 / HDU 1542 Atlantis 线段树求矩形面积并

题意:给出矩形两对角点坐标,求矩形面积并. 解法:线段树+离散化. 每加入一个矩形,将两个y值加入yy数组以待离散化,将左边界cover值置为1,右边界置为2,离散后建立的线段树其实是以y值建的树,线段树维护两个值:cover和len,cover表示该线段区间目前被覆盖的线段数目,len表示当前已覆盖的线段长度(化为离散前的真值),每次加入一条线段,将其y_low,y_high之间的区间染上line[i].cover,再以tree[1].len乘以接下来的线段的x坐标减去当前x坐标,即计算了一部

HDU 1828 / POJ 1177 Picture --线段树求矩形周长并

题意:给n个矩形,求矩形周长并 解法:跟求矩形面积并差不多,不过线段树节点记录的为: len: 此区间线段长度 cover: 此区间是否被整个覆盖 lmark,rmark: 此区间左右端点是否被覆盖 num: 此区间分离开的线段的条数 重点在转移的地方,不难理解. 代码: #include <iostream> #include <cmath> #include <iostream> #include <cstdio> #include <cstrin

POJ 1151 Atlantis 线段树+离散化

题目链接:http://poj.org/problem?id=1151  http://acm.hdu.edu.cn/showproblem.php?pid=1542 题目大意:给你几个矩形的坐标,求他们的面积的并. 解题思路:可以参考http://www.cnblogs.com/kuangbin/archive/2011/08/16/2140544.html,实际上就是一个方向直接算出,另一个方向使用线段树维护已经覆盖的底边的长度.具体操作不算复杂:假想一条扫描下从下往上开始进行扫描,初始时候

poj 1151 Atlantis (线段树+扫描线+离散化)

Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 18061   Accepted: 6873 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

POJ 1151 Atlantis( 线段树 + 扫描线 )

一维离散化, 扫描线扫另一维, 用线段树维护 POJ建议交C++...G++貌似double要用%f ? 反正同一份代码C++AC,G++WA ------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 109; struct Line { double p,

poj 1151 Atlantis (线段树+扫描线)

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

UVA 11983 Weird Advertisement --线段树求矩形问题

题意:给出n个矩形,求矩形中被覆盖K次以上的面积的和. 解法:整体与求矩形面积并差不多,不过在更新pushup改变len的时候,要有一层循环,来更新tree[rt].len[i],其中tree[rt].len[i]表示覆盖次数大于等于i的线段长度,以便求面积,最后只要每次都用tree[1].len[K]来算面积即可. 代码: #include <iostream> #include <cmath> #include <iostream> #include <cst

poj 3277 City Horizon (线段树 扫描线 矩形面积并)

题目链接 题意: 给一些矩形,给出长和高,其中长是用区间的形式给出的,有些区间有重叠,最后求所有矩形的面积. 分析: 给的区间的范围很大,所以需要离散化,还需要把y坐标去重,不过我试了一下不去重 也不会出错, 所有的区间都能列出来,只是在查找的时候费点事. 给的矩形相当于在同一水平线上的,也就是y1坐标相当于为0,其他的就和 poj 1151 Atlantis 差不多了. 我写的思路是按照矩形面积并的思路写的: 但是还有另一种方法也是挺简单的,就是把给的矩形按照高从小到大排序,然后依次插入线段树

UVA 11983 Weird Advertisement(线段树求矩形并的面积)

UVA 11983 题目大意是说给你N个矩形,让你求被覆盖k次以上的点的总个数(x,y<1e9) 首先这个题有一个转化,吧每个矩形的x2,y2+1这样就转化为了求N个矩形被覆盖k次以上的区域的面积 由于坐标很大,首先考虑的就是将坐标离散化,然后建立线段树tree[][K],表示x的某个区间被覆盖了K次(大于K次算K次)的实际长度,在计算时把矩形转化为一系列横线段(就是说将一个矩形拆开为两条线段,下面的标记为1,上面的标记为-1(这里的标记很有技巧)),然后将这些线段按照y值的从小到达排序(y值相