POJ 1151 Atlantis(扫描线)
Posted lipeiyi520
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1151 Atlantis(扫描线)相关的知识,希望对你有一定的参考价值。
题目原链接:http://poj.org/problem?id=1151
题目中文翻译:
POJ 1151 Atlantis
Time Limit: 1000MS |
Memory Limit: 10000K |
|
Total Submissions: 25769 |
Accepted: 9477 |
Description
有几个古希腊文本包含传说中的亚特兰蒂斯岛的描述。 其中一些文本甚至包括岛屿部分地图。 但不幸的是,这些地图描述了亚特兰蒂斯的不同区域。 您的朋友Bill必须知道地图的总面积。 你(不明智地)自告奋勇写了一个计算这个数量的程序。
Input
输入包含几个测试用例。 每个测试用例都以一行包含一个整数n(1 <= n <= 100)开始,指示可用的地图。以下n行描述了每个地图。 这些行中的每一行包含四个数字x1; y1; x2; y2(0 <= x1 <x2 <= 100000; 0 <= y1 <y2 <= 100000),不一定是整数。 值(x1; y1)和(x2; y2)是地图左上角和右下角的坐标。
输入文件以包含单个0的行作为终止。不处理它。
Output
对于每个测试用例,您的程序应输出一个部分。 每个部分的第一行必须是“Test case #k”,其中k是测试用例的编号(从1开始)。 第二个必须是“Total explored area:a”,其中a是总探索区域(即此测试用例中所有矩形的覆盖区域),精确到小数点后两位数。
在每个测试用例后输出一个空行。
Sample Input
2
10 10 20 20
15 15 25 25.5
0
Sample Output
Test case #1
Total explored area: 180.00
解题思路:
本人太菜,无法描述,请看大佬详解:AKIOI
AC代码:
(由此大佬博客借鉴而来:code)
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 5 using namespace std; 6 7 struct kkk{//线段树 8 int l,r;//线段树的左右整点 9 int c;//c用来记录重叠情况 10 double cnt,lf,rf;//cnt用来计算实在的长度,lf,rf分别是对应的左右真实的浮点数端点 11 }s[603]; 12 13 struct k2{ 14 double x,y1,y2; 15 int f; 16 }l[603]; 17 //把一段段平行于y轴的线段表示成数组 , 18 //x是线段的x坐标,y1,y2线段对应的下端点和上端点的坐标 19 //一个矩形 ,左边的那条边f为1,右边的为-1, 20 //用来记录重叠情况,可以根据这个来计算,kkk节点中的c 21 22 double y[201];//记录y坐标的数组 23 24 bool cmp(k2 a,k2 b) { 25 return a.x < b.x; 26 } 27 28 void build(int t,int l,int r) { 29 s[t].l = l;s[t].r = r; 30 s[t].cnt = s[t].c = 0; 31 s[t].lf = y[l]; 32 s[t].rf = y[r]; 33 if(l + 1 == r) return ; 34 int mid = (l + r) >> 1; 35 build(t << 1,l,mid); 36 build(t << 1 | 1,mid,r); 37 } 38 39 void calen(int t) {//计算长度 40 if(s[t].c > 0) {//不是最后一条出边 41 s[t].cnt = s[t].rf - s[t].lf; 42 return ; 43 } 44 if(s[t].l + 1 == s[t].r) s[t].cnt = 0;//因为用左闭右开数组,所以长度为0,就相当于一个点 45 else s[t].cnt = s[t<<1].cnt + s[t<<1|1].cnt;//否则用儿子计算自己 46 } 47 48 void update(int t,k2 e) {//加入线段e,后更新线段树 49 if(e.y1 == s[t].lf && e.y2 == s[t].rf) {//如果正好找到区间 50 s[t].c += e.f; 51 calen(t); 52 return ; 53 } 54 if(e.y2 <= s[t<<1].rf) update(t<<1,e);//下传左儿子 55 else if(e.y1 >= s[t<<1|1].lf) update(t<<1|1,e);//下传右儿子 56 else {//左右儿子都下传 57 k2 tmp = e; 58 tmp.y2 = s[t<<1].rf; 59 update(t<<1,tmp); 60 tmp = e; 61 tmp.y1 = s[t<<1|1].lf; 62 update(t<<1|1,tmp); 63 } 64 calen(t); 65 } 66 67 int main() { 68 int i,n,t,aa = 0; 69 double x1,y1,x2,y2; 70 while(scanf("%d",&n),n) { 71 aa++; 72 t = 1; 73 for(int i = 1;i <= n; i++) { 74 scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); 75 l[t].x = x1; 76 l[t].y1 = y1; 77 l[t].y2 = y2; 78 l[t].f = 1; 79 y[t++] = y1; 80 l[t].x = x2; 81 l[t].y1 = y1; 82 l[t].y2 = y2; 83 l[t].f = -1; 84 y[t++] = y2; 85 } 86 sort(l+1,l+t,cmp); 87 sort(y+1,y+t); 88 build(1,1,t-1);//建树 89 update(1,l[1]);//下传lazy标记 90 double res = 0; 91 for(int i = 2;i < t; i++) { 92 res += s[1].cnt * (l[i].x - l[i-1].x); 93 update(1,l[i]); 94 } 95 printf("Test case #%d\\nTotal explored area: %.2f\\n\\n",aa,res); 96 } 97 }
以上是关于POJ 1151 Atlantis(扫描线)的主要内容,如果未能解决你的问题,请参考以下文章