HDU 1542 Atlantis(扫描线)题解
题意:给n个可能相交的矩形,问你不重复的总面积
思路:扫描线,一边扫一边加。
扫描线:图片来源:理解扫描线
假设我们要算以下四个矩形面积,显然中间深色的是重复的。我们按照x的大小,从左往右扫,然后用线段树维护y轴向的长度就可以了。但是,我们不能用点去维护y轴坐标,而是抽象成把点i看成y[i]到y[i+1]这个区间,不然会有错。
代码:
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
typedef long longll;
using namespace std;
const int maxn = + ;
const int MOD = 1e9 + ;
const int INF = 0x3f3f3f3f;
struct Bian{
double x, y1, y2;
int flag;
bool operator < (const Bian &a) const{
return x < a.x;
}
}bian[maxn << ];
double y[maxn << ]; //离散化定位
int n, cnt;
int Find(double x){ //在y中离散化后位置
int l = , r = cnt, ans = ;
while(l <= r){
int m = (l + r) >> ;
if(fabs(y[m] - x) < 1e-) ans = m;
if(y[m] > x) r = m - ;
else l = m + ;
}
return ans;
}
int cover[maxn << ]; //y的覆盖次数
double sum[maxn << ];
void pushUp(int l, int r, int rt){
if(cover[rt] > ) sum[rt] = y[r + ] - y[l];
//全覆盖了
else if(l == r) sum[rt] = ;
//没覆盖的叶子结点
else sum[rt] = sum[rt << ] + sum[rt << | ];
//部分覆盖
}
void build(int l, int r, int rt){
if(l == r){
cover[rt] = sum[rt] = ;
return;
}
int m = (l + r) >> ;
build(l, m, rt << );
build(m + , r, rt << | );
cover[rt] = sum[rt] = ;
}
void update(int L, int R, int l, int r, int v, int rt){
if(L <= l && R >= r){
cover[rt] += v;
pushUp(l, r, rt);
return;
}
int m = (l + r) >> ;
if(L <= m)
update(L, R, l, m, v, rt << );
if(R > m)
update(L, R, m + , r, v, rt << | );
pushUp(l, r, rt);
}
int main(){
int ca = ;
while(scanf("%d", &n) && n){
for(int i = ; i <= n; i++){
double x1, x2, y1, y2;
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
int ll = * i - , rr = * i;
bian[ll].x = x1, bian[ll].y1 = y1, bian[ll].y2 = y2;
bian[ll].flag = ;
bian[rr].x = x2, bian[rr].y1 = y1, bian[rr].y2 = y2;
bian[rr].flag = -;
y[ll] = y1, y[rr] = y2; //定位用的
}
n = n + n;
sort(bian + , bian + n + );
sort(y + , y + n + ); cnt = ; //unique
for(int i = ; i <= n; i++){
if(y[i] != y[i - ]){
y[++cnt] = y[i];
}
} double ans = ;
build(, cnt, );
for(int i = ; i < n; i++){
update(Find(bian[i].y1), Find(bian[i].y2) - , , cnt, bian[i].flag, );
ans += sum[] * (bian[i + ].x - bian[i].x);
}
printf("Test case #%d\n", ca++);
printf("Total explored area: %.2lf\n\n", ans);
}
return ;
}
HDU 1542 Atlantis(扫描线)题解的更多相关文章
- POJ 1151 HDU 1542 Atlantis(扫描线)
题目大意就是:去一个地方探险,然后给你一些地图描写叙述这个地方,每一个描写叙述是一个矩形的右下角和左上角.地图有些地方是重叠的.所以让你求出被描写叙述的地方的总面积. 扫描线的第一道题,想了又想,啸爷 ...
- (HDU 1542) Atlantis 矩形面积并——扫描线
n个矩形,可以重叠,求面积并. n<=100: 暴力模拟扫描线.模拟赛大水题.(n^2) 甚至网上一种“分块”:分成n^2块,每一块看是否属于一个矩形. 甚至这个题就可以这么做. n<=1 ...
- HDU 1542 Atlantis(矩形面积并)
HDU 1542 Atlantis 题目链接 题意:给定一些矩形,求面积并 思路:利用扫描线,因为这题矩形个数不多,直接暴力扫就能够了.假设数据大.就要用线段树 代码: #include <cs ...
- HDU 1542 Atlantis(线段树扫描线+离散化求面积的并)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- HDU 1542 - Atlantis - [线段树+扫描线]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542 Time Limit: 2000/1000 MS (Java/Others) Memory Li ...
- hdu 1542 Atlantis(线段树,扫描线)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- hdu 1542 Atlantis(段树&扫描线&面积和)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- (中等) HDU 1542 Atlantis,扫描线。
Problem Description There are several ancient Greek texts that contain descriptions of the fabled is ...
- HDU 1542 Atlantis (线段树 + 扫描线 + 离散化)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
随机推荐
- mysql数据库的查询,添加,删除,还原,备份
18章数据mariadb数据库 1.setup 配置网卡centos6.52.nmtui 网卡图形配置界面3.yum install mariadb mariadb-server4.systemctl ...
- Python_tkinter(4)_上传文件
1.上传单个文件 import tkinter as tk from tkinter import filedialog def upload_file(): selectFile = tk.file ...
- rabbit_mq实现分布式事务
gitlab下载地址: 一.rabbitmq实现原理 一般在自己内部系统中建议采用lcn刚性事务来处理,面对调用第三方接口,或者夸平台语言是采用消息中间来实现补偿型事务.注意在进行补偿时需要注意重复调 ...
- JDBC 查询
//查询""SMITH"的empno import java.sql.Connection; import java.sql.DriverManager; import ...
- Python insert()方法--list
描述 insert()方法:用于向列表中指定的索引位置之前插入新的对象,因为是在对应目标之前插入,故此方法无法像append()方法一样将对象添加到列表末尾. 语法 语法格式:list.insert( ...
- Linux系统中存储设备的两种表示方法
转:https://blog.csdn.net/holybin/article/details/38637381 一.对于IDE接口的硬盘的两种表示方法: 1.IDE接口硬盘,对于整块硬盘的两种表示方 ...
- 007-chrome插件系列
1.Axure RP Extension for Chrome 2.Charset 3.CLEAN crxMouse Gestures 4.Google 翻译 5.JSONView 6.restlet
- 2018-2019-2 20165236 《网络对抗技术》Exp4 恶意代码分析
2018-2019-2 20165236 <网络对抗技术>Exp4 恶意代码分析 一.1.实践目标 1.1是监控你自己系统的运行状态,看有没有可疑的程序在运行; 1.2是分析一个恶意软件, ...
- 【Linux】Set CentOS no GUI default
[root@localhost ~]#vi /etc/inittab 重点看下面这部分代码 # 0 - halt (Do NOT set initdefault to this) ...
- Oracle 10g RAC OCR、Voting disk更换
环境:OEL 5.7 + Oracle 10.2.0.5 RAC 需求:更换存储,OCR.Voting disk同时需要更换到新存储. 1.替换OCR 2.替换voting disk 1.替换OCR ...