传送门

题目描述

有几个古希腊书籍中包含了对传说中的亚特兰蒂斯岛的描述。

其中一些甚至包括岛屿部分地图。

但不幸的是,这些地图描述了亚特兰蒂斯的不同区域。

您的朋友Bill必须知道地图的总面积。

你自告奋勇写了一个计算这个总面积的程序。

输入格式

输入包含多组测试用例。

对于每组测试用例,第一行包含整数n,表示总的地图数量。

接下来n行,描绘了每张地图,每行包含四个数字x1,y1,x2,y2x1,y1,x2,y2(不一定是整数),(x1,y1)(x1,y1)和(x2,y2)(x2,y2)分别是地图的左上角位置和右下角位置。

当输入用例n=0时,表示输入终止,该用例无需处理。

输出格式

每组测试用例输出两行。

第一行输出”Test case #k”,其中k是测试用例的编号,从1开始。

第二行输出“Total explored area:a”,其中a是总地图面积(即此测试用例中所有矩形的面积并,注意如果一片区域被多个地图包含,则在计算总面积时只计算一次),精确到小数点后两位数。

在每个测试用例后输出一个空行。

数据范围

1≤n≤100,
0≤x1<x2≤100000,
0≤y1<y2≤100000

输入样例:

2
10 10 20 20
15 15 25 25.5
0

输出样例:

Test case #1
Total explored area: 180.00

题意:求面积并

题解:扫描线。

   如果题目给出的矩形如下:

   

    

    那么我们要求的总面积为:

    

   我们如果用一条竖直的直线从左到右扫过整个坐标系,那么直线上在所求面积中的覆盖长度L只会在每个矩形的左右边界发生变化,整个图形可以被分成2*n段,每一段直线被覆盖的长度L都是固定的,这一段的面积为L*∆x。

    

    我们知道∆x是两个相邻的x之间的间距,那我们要怎么维护每一段L的长度?

    对于每个矩形,我们把左边界记为一个四元组:(x1,y1,y2,1),把右边界记为(x2,y1,y2,-1)(假设x1<x2,y1<y2)。我们可以按纵坐标维护一个线段树,当直线扫过矩形的左边界时,相当于在线段树中把区间[y1,y2](y1<y2)的值都加上1(插入区间[y1,y2]),当直线扫过矩形的右边界时,相当于在线段树中把区间[y1,y2]的值都减去1(减去区间[y1,y2]),只要有位置值大于0就代表这是线段的一部分(算区间长度)。因为y的范围很大所以我们要先离散化一下。我们在线段树中定义cnt来记录这段区间出现了多少次,定义len来记录直线长度。每次将直线更新之后,根结点中存的长度就是当前段L的大小。

        

代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = + ;
struct node{
double x,y1,y2;
int val;
node() {}
node(double x, double y1, double y2,int val){
this->x = x; this->val = val;
this->y1 = y1; this->y2 = y2;
}
bool operator <(const node &t)const {
return x<t.x;
}
};
struct Tree{
int l,r,cnt;
double len;
}t[]; //找了一个小时的段错误,结果是*4小了???
int n,k=;
vector<node> a;
vector<double> y;
void up(int rt) {
if (t[rt].cnt>) t[rt].len = y[t[rt].r+] - y[t[rt].l];
else t[rt].len = t[rt<<].len + t[rt<<|].len;
}
void build(int rt,int l,int r) {
t[rt].l = l,t[rt].r = r; t[rt].cnt = ;
t[rt].len = ;
if (l == r) return;
int mid = (l+r)>>;
build(rt<<,l,mid);
build(rt<<|,mid+,r);
}
void update(int rt,int l,int r,int val) {
if (l <= t[rt].l && r >= t[rt].r) {
t[rt].cnt+=val;
up(rt);
return;
}
int mid = (t[rt].l+t[rt].r)>>;
if (l <= mid) update(rt<<,l,r,val);
if (r > mid) update(rt<<|,l,r,val);
up(rt);
}
int main() {
while (~scanf("%d",&n) && n) {
y.clear();a.clear();
for(int i = ; i < n; i++) {
double x1,x2,y1,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
y.push_back(y1);
y.push_back(y2);
a.push_back(node(x1,y2,y1,));
a.push_back(node(x2,y2,y1,-));
}
y.push_back(-);
sort(a.begin(),a.end());
sort(y.begin(),y.end());
y.erase(unique(y.begin(),y.end()),y.end());
int m = y.size(),num = a.size();
build(,,m);
double ans = ;
for (int i = ; i < num; i++) {
int l = lower_bound(y.begin(),y.end(),a[i].y2)-y.begin();
int r = lower_bound(y.begin(),y.end(),a[i].y1) - y.begin()-;
update(,l,r,a[i].val);
ans += t[].len*(a[i+].x-a[i].x);
}
printf("Test case #%d\n",k++);
printf("Total explored area: %.2f\n\n",ans);
}
return ;
}

  

PS:注意数组开大一点   

AcWing 247. 亚特兰蒂斯 | 扫描线的更多相关文章

  1. AcWing 247. 亚特兰蒂斯 (线段树,扫描线,离散化)

    题意:给你\(n\)个矩形,求矩形并的面积. 题解:我们建立坐标轴,然后可以对矩形的横坐标进行排序,之后可以遍历这些横坐标,这个过程可以想像成是一条线从左往右扫过x坐标轴,假如这条线是第一次扫过矩形的 ...

  2. AcWing 248. 窗内的星星 (扫描线)打卡

    题目:https://www.acwing.com/problem/content/250/ 题意:给你n个点,现在问你能每个点都有个权值,问你能覆盖最多的权值是多少,边界不算 思路:这个其实和我之前 ...

  3. ACWing 248. 窗内的星星|扫描线+懒惰标记

    传送门 题目描述 在一个天空中有很多星星(看作平面直角坐标系),已知每颗星星的坐标和亮度(都是整数). 求用宽为W.高为H的矩形窗户(W,H为正整数)能圈住的星星的亮度总和最大是多少.(矩形边界上的星 ...

  4. 【学习笔记】线段树—扫描线补充 (IC_QQQ)

    [学习笔记]线段树-扫描线补充 (IC_QQQ) (感谢 \(IC\)_\(QQQ\) 大佬授以本内容的著作权.此人超然于世外,仅有 \(Luogu\) 账号 尚可膜拜) [学习笔记]线段树详解(全) ...

  5. 线段树扫描线(一、Atlantis HDU - 1542(覆盖面积) 二、覆盖的面积 HDU - 1255(重叠两次的面积))

    扫描线求周长: hdu1828 Picture(线段树+扫描线+矩形周长) 参考链接:https://blog.csdn.net/konghhhhh/java/article/details/7823 ...

  6. 【Codeforces720D】Slalom 线段树 + 扫描线 (优化DP)

    D. Slalom time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...

  7. Codeforces VK CUP 2015 D. Closest Equals(线段树+扫描线)

    题目链接:http://codeforces.com/contest/522/problem/D 题目大意:  给你一个长度为n的序列,然后有m次查询,每次查询输入一个区间[li,lj],对于每一个查 ...

  8. HUD 4007 [扫描线][序]

    /* 大连热身B题 不要低头,不要放弃,不要气馁,不要慌张 题意: 坐标平面内给很多个点,放置一个边长为r的与坐标轴平行的正方形,问最多有多少个点在正方形内部. 思路: 按照x先排序,然后确定x在合法 ...

  9. Atitit 图像扫描器---基于扫描线

    Atitit 图像扫描器---基于扫描线 调用范例 * @throws FileExistEx */ public static void main(String[] args) throws Fil ...

随机推荐

  1. ubuntu环境变量的三种设置方法

    一:设置环境变量的三种方法 1.1 临时设置 export PATH=/home/yan/share/usr/local/arm/3.4.1/bin:$PATH 1.2 当前用户的全局设置 打开~/. ...

  2. HDU 1875 最小生成树prim算法

    #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #inc ...

  3. Python--day24--多继承

    如果本生没有func方法的话就调用距离自己最近的基类的方法 钻石继承: 查找方法的顺序:如下例的找func方法(广度优先) 例1: 例2: 漏斗继承: 小乌龟继承问题:(最顶端的节点F是最后查找的) ...

  4. 洛谷P1595 信封问题 题解 错排问题

    作者:zifeiy 标签:排列组合,错排问题 题目链接:https://www.luogu.org/problem/P1595 题目描述:某人写了n封信和n个信封,如果所有的信都装错了信封.求所有信都 ...

  5. 判断当前所使用python的版本和来源

    import sys print(sys.prefix) print(sys.executable) 怎样判断当前py文件在什么版本的python环境下运行 import sys print(sys. ...

  6. [转]爬虫 selenium + phantomjs / chrome

    目录 selenium 模块 安装 phantomjs 浏览器 安装 chromedriver 接口 安装 对比两个接口 整合使用 基本实例 常用属性方法 定位节点 节点操作 其他操作 实例解析 - ...

  7. Python--day40--threading模块

    import time from threading import Thread class MyThread(Thread): def __init__(self,arg): super().__i ...

  8. C# const 和 readonly 有什么区别

    在写常量的时候,是选择使用 const 还是 static readonly 是一个让人难以决定的问题,本文告诉大家这两个方法的区别 如果一个类有静态字段,会如何初始化 可以使用的方法有两个,第一个方 ...

  9. P1082 数列分段

    题目描述 对于给定的一个长度为 \(N\) 的正整数数列 \(A_i\) ,现要将其分成连续的若干段,并且每段和不超过 \(M\) (可以等于 \(M\) ),问最少能将其分成多少段使得满足要求. 输 ...

  10. H3C查看系统启动配置文件