博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
poj1151 Atlantis
阅读量:4573 次
发布时间:2019-06-08

本文共 3856 字,大约阅读时间需要 12 分钟。

                               Atlantis

                   Time Limit: 1000MS    Memory Limit: 10000K

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.Description

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

210 10 20 2015 15 25 25.50

Sample Output

Test case #1Total explored area: 180.00

Source

题解:

  我们在y轴方向上维护一棵线段树,其目的是区间覆盖,即应对向某个区间有没有被覆盖这样的查询,以及添加覆盖和删除覆盖这样的操作-----也即是将矩形的左右边界看做对y轴的覆盖来处理。
  每次处理到一条线段的同时,我们首先统计线段树中已经被覆盖的长度,让 ans+=delta*T.sum ,delta为这一次与上一次两次操作x轴的变化量。如果还不理解,就去网上查查扫描线算法吧。
然后的问题就是如何来维护这样一棵线段树,最暴力的方法就是把y轴看成一个序列,这个序列有0和非零元素,0代表没有被覆盖,>0的元素代表这个点被覆盖的层数,每次查询就是找非0区间的长度,注意:点和区间有一定区别,注意转化。
  但是如果y的范围比较大,建树和维护都相当耗时间,因此需要改造一下线段树维护的内容。
  我们把每个矩形的左右线段的端点单独捞出来,放在 y[] 里,进行排序,然后对于 y[] 来建立线段树。
  例如,有一组数据是:2
                                    1 1 3 3
                                    2 1.5 4 4
  那么y={1,1.5,3,4} 我们建立堆型的存储结构,tree[1].left=1 tree[1].right=4 意思是线段树的节点1维护y[1]到y[4]之间的区间,它的左孩子tree[2].left=1,tree[2].right=2,维护y[1]到y[2]之间的区间,这已经是区间的最小单位了,所以tree[2]就是叶子节点。对于tree[1]的右孩子tree[3],它维护的是y[2]到y[4]之间的区间,由于线段树维护的是区间,所以建树build()中对于建立右孩子为 build((t<<1)+1,mid,right); mid不+1。
  tree[x].c是x节点维护的区间的覆盖的层数,只有此区间被完全覆盖,才能tree[x].c++;删除操作也一样
  然后update(root)就是计算测度,即覆盖长度

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 using namespace std; 8 const int N=210; 9 struct node{ 10 int left,right,c; //c : 区间被覆盖的层数, m: 区间的测度 11 double m; 12 }tree[N*4]; 13 struct Line{ 14 double x,y1,y2; //纵方向直线, x:直线横坐标, y1 y2:直线上的下面与上面的两个纵坐标 15 int s; //s = 1 : 直线为矩形的左边, s = 0:直线为矩形的右边 16 }line[N]; 17 bool cmp(Line a,Line b){ 18 return a.x
>1; 28 build(t<<1,left,mid); 29 build((t<<1)+1,mid,right); 30 } 31 } 32 void update(int t){ 33 if(tree[t].c>0) tree[t].m=y[tree[t].right]-y[tree[t].left]; 34 //将线段树上区间的端点分别映射到 y[]数组所对应的浮点数上,由此计算出测度 35 else if(tree[t].left+1==tree[t].right) tree[t].m=0; 36 else tree[t].m=tree[t<<1].m+tree[(t<<1)+1].m; 37 } 38 void insert(int t,int left,int right){ 39 if(left<=tree[t].left && tree[t].right<=right){ 40 tree[t].c++; 41 update(t); 42 return ; 43 } 44 int mid=(tree[t].left+tree[t].right)>>1; 45 if(left
mid) insert((t<<1)+1,left,right); 47 update(t); 48 } 49 void del(int t,int left,int right){ 50 if(left<=tree[t].left && tree[t].right<=right){ 51 tree[t].c--; 52 update(t); 53 return ; 54 } 55 int mid=(tree[t].left+tree[t].right)>>1; 56 if(left
mid) del((t<<1)+1,left,right); 58 update(t); 59 } 60 61 int getindex(int n,double x){ //二分查找出浮点数 t 在数组y[]中的位置(此即所谓的映射关系) 62 int left,right,mid; 63 left=1;right=n; 64 while(left<=right){ 65 mid=(left+right)>>1; 66 if(y[mid]

 

转载于:https://www.cnblogs.com/CXCXCXC/p/5003389.html

你可能感兴趣的文章
Fortran编译器
查看>>
初识go
查看>>
将一张表中的部分记录插入到另一张表中
查看>>
晒一个山寨版的快盘----在.net下使用快盘API
查看>>
angular4路由设置笔记
查看>>
Oracle数据库的基础(1)
查看>>
关于Store Apps
查看>>
实现ajax
查看>>
【C#文件夹锁】C#文件夹加锁小工具
查看>>
mysql 数据库路径
查看>>
web服务器负载均衡部署及实现
查看>>
13.JOIN
查看>>
省市县三级联动
查看>>
多IP地址--笔记
查看>>
react native开发日记
查看>>
Virtual Dom是什么
查看>>
阶乘之和
查看>>
Unable to instantiate receiver xxx.receiver.NetworkReceiver异常
查看>>
C++调用C#类库函数
查看>>
vs2013编译项目去掉warning信息
查看>>