POJ1151 Atlantis 【扫描线】
| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 16882 | Accepted: 6435 |
Description
total area for which maps exist. You (unwisely) volunteered to write a program that calculates this quantity.
Input
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
(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
我累个去~~这题从早上8:30一直做到如今22:50,总算是A掉了,上午一直没看懂扫描线,然后看到傍晚总算是有些头目了,结果写的时候非常生疏,等到摸摸索索完全然全地写完已经大半夜了。满心欢喜地提交又各种RE,開始以为是数组开小了,然后翻了倍依然RE,就这样RE了6、7次后猛地发现是freopen忘了凝视掉,o(╯□╰)o...尼玛啊!!总归是在睡觉前找到问题了。
题意:给定n个矩形的对角坐标,各自是左下和右上,浮点型。求矩形覆盖的面积。
题解:扫描线解法,将每一个矩形分别以长宽为直线切割,终于垂直于x轴的割线有2n条,垂直于y轴的割线也有2n条,将这些割线存到两个数组里并排序,建立一个线段树用以维护扫描线当前在y轴方向覆盖的长度。最后,在扫描线从左往右扫描的过程中,一旦经过一条垂直于x轴的割线就立刻将这条割线更新到线段树里,覆盖面积即为两条相邻扫描线的距离乘以左边一条扫描线的长度,累加下去即得终于覆盖面积。x轴割线数组须要记录边是入边还是出边。若是出边则右边的的面积对此出边是不计的,可是存在入边重合的情况,须要详细考虑。
2014-9-23 23:32:51更新
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define maxn 202
#define lson l, mid, rt << 1
#define rson mid, r, rt << 1 | 1
using namespace std; struct Node {
double y1, y2, len;
int covers;
} T[maxn << 2];
struct Node2 {
double x, y1, y2;
int isLeft;
} xNode[maxn];
double yNode[maxn]; bool cmp(Node2 a, Node2 b) {
return a.x < b.x;
} void pushUp(int l, int r, int rt) {
if(T[rt].covers > 0)
T[rt].len = T[rt].y2 - T[rt].y1;
else if(r - l == 1) T[rt].len = 0.0;
else T[rt].len = T[rt << 1].len + T[rt << 1 | 1].len;
} void build(int l, int r, int rt) {
T[rt].covers = 0;
T[rt].y1 = yNode[l];
T[rt].y2 = yNode[r];
T[rt].len = 0.0;
if(r - l == 1) return;
int mid = (l + r) >> 1;
build(lson);
build(rson);
} void update(Node2 x, int l, int r, int rt) {
if(x.y1 == T[rt].y1 && x.y2 == T[rt].y2) {
T[rt].covers += x.isLeft;
pushUp(l, r, rt);
return;
}
int mid = (l + r) >> 1;
if(x.y2 <= yNode[mid]) update(x, lson);
else if(x.y1 >= yNode[mid]) update(x, rson);
else {
Node2 x1 = x, x2 = x;
x1.y2 = x2.y1 = yNode[mid];
update(x1, lson);
update(x2, rson);
}
pushUp(l, r, rt);
} int main() {
//freopen("stdin.txt", "r", stdin);
int n, i, id, cas = 1;
double x1, y1, x2, y2, sum;
while(scanf("%d", &n), n) {
for(i = id = 0; i < n; ++i) {
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
yNode[id] = y1;
xNode[id].x = x1;
xNode[id].y1 = y1;
xNode[id].y2 = y2;
xNode[id++].isLeft = 1; yNode[id] = y2;
xNode[id].x = x2;
xNode[id].y1 = y1;
xNode[id].y2 = y2;
xNode[id++].isLeft = -1;
}
sort(yNode, yNode + id);
build(0, id - 1, 1);
sort(xNode, xNode + id, cmp);
update(xNode[0], 0, id - 1, 1);
for(i = 1, sum = 0.0; i < id; ++i) {
sum += T[1].len * (xNode[i].x - xNode[i-1].x);
update(xNode[i], 0, id - 1, 1);
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n", cas++, sum);
}
return 0;
}
#include <stdio.h>
#include <algorithm>
#define maxn 202
#define lson l, mid, rt << 1
#define rson mid, r, rt << 1 | 1
using std::sort; struct Node{
double y1, y2, height; //y1, y2记录y坐标离散前的值
int coverTimes;
} tree[maxn << 2]; //区间树
double yArr[maxn]; //垂直于Y轴的割线
struct node{
double x, y1, y2;
int isLeftEdge;
} xArr[maxn]; //垂直于X轴的割线 bool cmp(node a, node b){ return a.x < b.x; } void build(int l, int r, int rt)
{
tree[rt].coverTimes = 0;
tree[rt].height = 0;
tree[rt].y1 = yArr[l];
tree[rt].y2 = yArr[r];
if(r - l == 1) return; int mid = (l + r) >> 1;
build(lson);
build(rson);
} void getSweepLinesHeight(int l, int r, int rt)
{//因为存在线段覆盖的情况,所以长线段结束并不能代表扫描线长度为0
if(tree[rt].coverTimes > 0){
tree[rt].height = tree[rt].y2 - tree[rt].y1;
}else if(r - l == 1){
tree[rt].height = 0;
}else tree[rt].height = tree[rt << 1].height + tree[rt << 1 | 1].height;
} void update(node xNode, int l, int r, int rt)
{
if(xNode.y1 == tree[rt].y1 && xNode.y2 == tree[rt].y2){
tree[rt].coverTimes += xNode.isLeftEdge;
getSweepLinesHeight(l, r, rt);
return;
} //include r - l == 1 int mid = (l + r) >> 1;
if(xNode.y2 <= yArr[mid]) update(xNode, lson);
else if(xNode.y1 >= yArr[mid]) update(xNode, rson);
else{
node temp = xNode;
temp.y2 = yArr[mid];
update(temp, lson);
temp = xNode; temp.y1 =yArr[mid];
update(temp, rson);
} getSweepLinesHeight(l, r, rt); //Attention!
} int main()
{
//freopen("stdin.txt", "r", stdin);
int n, i, cas = 1, id;
double x1, y1, x2, y2, sum;
while(scanf("%d", &n), n){
for(i = id = 0; i < n; ++i){
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
yArr[id] = y1; xArr[id].x = x1;
xArr[id].isLeftEdge = 1; //1表示左。-1表示右
xArr[id].y1 = y1; xArr[id++].y2 = y2; yArr[id] = y2; xArr[id].x = x2;
xArr[id].isLeftEdge = -1;
xArr[id].y1 = y1; xArr[id++].y2 = y2;
} sort(yArr, yArr + id);
sort(xArr, xArr + id, cmp);
build(0, id - 1, 1); update(xArr[0], 0, id - 1, 1);
for(i = 1, sum = 0; i < id; ++i){
sum += tree[1].height * (xArr[i].x - xArr[i - 1].x);
update(xArr[i], 0, id - 1, 1);
} printf("Test case #%d\nTotal explored area: %.2lf\n\n", cas++, sum);
}
return 0;
}
POJ1151 Atlantis 【扫描线】的更多相关文章
- poj1151 Atlantis——扫描线+线段树
题目:http://poj.org/problem?id=1151 经典的扫描线问题: 可以用线段树的每个点代表横向被矩形上下边分割开的每一格,这样将一个矩形的出现或消失化为线段树上的单点修改: 每个 ...
- [POJ1151]Atlantis
[POJ1151]Atlantis 试题描述 There are several ancient Greek texts that contain descriptions of the fabled ...
- ACM学习历程—POJ1151 Atlantis(扫描线 && 线段树)
Description There are several ancient Greek texts that contain descriptions of the fabled island Atl ...
- poj1151 Atlantis (线段树+扫描线+离散化)
有点难,扫描线易懂,离散化然后线段树处理有点不太好理解. 因为这里是一个区间,所有在线段树中更新时,必须是一个长度大于1的区间才是有效的,比如[l,l]这是一根线段,而不是区间了. AC代码 #inc ...
- POJ1151 Atlantis 线段树扫描线
扫描线终于看懂了...咕咕了快三个月$qwq$ 对于所有的横线按纵坐标排序,矩阵靠下的线权值设为$1$,靠上的线权值设为$-1$,然后执行线段树区间加减,每次的贡献就是有效宽度乘上两次计算时的纵坐标之 ...
- POJ 1151 HDU 1542 Atlantis(扫描线)
题目大意就是:去一个地方探险,然后给你一些地图描写叙述这个地方,每一个描写叙述是一个矩形的右下角和左上角.地图有些地方是重叠的.所以让你求出被描写叙述的地方的总面积. 扫描线的第一道题,想了又想,啸爷 ...
- POJ 1151 Atlantis (扫描线+线段树)
题目链接:http://poj.org/problem?id=1151 题意是平面上给你n个矩形,让你求矩形的面积并. 首先学一下什么是扫描线:http://www.cnblogs.com/scau2 ...
- POJ-1151 Atlantis 矩形面积并
题目链接:http://poj.org/problem?id=1151 扫描线+离散+线段树,线段树每个节点保存的是离散后节点右边的线段. //STATUS:C++_AC_16MS_208KB #in ...
- POJ1151 Atlantis 水题 计算几何
http://poj.org/problem?id=1151 想学一下扫描线线段树,结果写了道水题. #include<iostream> #include<cstdio> # ...
随机推荐
- 【DP悬线法】奶牛浴场
虽然还是悬线法,但是这道题可不能轻易地套模板了,而是要换一种思路,横着扫一遍,竖着扫一遍,时间复杂度依旧是O(n^2),然而空间复杂度有一定的优化 如果用原来的方法,显然时间空间都会炸(如果你想用ma ...
- SHRINK SPACE Command : Online Segment Shrink for Tables, LOBs and IOTs
ORACLE-BASE - ALTER TABLE ... SHRINK SPACE Command : Online Segment Shrink for Tables, LOBs and IOTs ...
- Spring Boot (18) @Async异步
通常我们在某网站发送邮件验证码时,首先会提示验证码已发送,然而此时可能没有收到验证码,过几秒种才真正的收到.如果是同步会先验证发送是否成功然后再通知,如果是异步可以先通知用户已发送,并释放请求,然后再 ...
- SQL Server2008优化之SET STATISTICS开关
一.准备工作 缓存对于某个查询的性能影响十分之大,所以优化之前要清空缓存. 清除Buffer Pool时面的所有缓存 DBCC DROPCLEANBUFFERS清除Buffer Pool里的所有缓存的 ...
- MFC 缩放和显示IplImage
序言:使用OpenCV嵌入MFC的框内,图像大小不能和框大小进行匹配,因此需要缩放,使图像适用于MFC框. 后来找到了一种新的方法,此方案貌似u已经废弃. (1).在MFC中显示图片 void CAv ...
- js-undefinde的一点延伸
前面写过一篇js中变量定义的问题:Js中判断变量存不存在的问题 本文再补充下,变量声明未初始化的情况,代码: <script> var a; alert(a==undefined)//tr ...
- socket主要函数介绍
1. 基本套接字函数(1)socket函数原型 socket(建立一个socket文件描述符) 所需头文件 #include <sys/types.h> #include <sy ...
- 【udacity】机器学习-knn最近邻算法
Evernote Export 1.基于实例的学习介绍 不同级别的学习,去除所有的数据点(xi,yi),然后放入一个数据库中,下次直接提取数据 但是这样的实现方法将不能进行泛化,这种方式只能简单的 ...
- https证书安装无效的主要原因
https证书的作用是为了确认服务端身份,但网络上充满了无效的证书,浏览器对使用无效证书的访问,给出危险.不安全警告,将是否选择继续访问由用户选择,而大多数用户是无法区分这是配置还是真的存在安全问题. ...
- 修复Thinkphp框架5.0和5.1版本的远程代码执行安全漏洞
由于框架对控制器名没有进行足够的检测会导致在没有开启强制路由的情况下可能的getshell漏洞.最直接的影响为index.php直接被篡改成首页html的内容! 5.0版本 thinkphp/libr ...