HDU 1542 矩形面积并【离散化+线段树+扫描线】
题目大意:
给你n个矩形,求出它们面积的并。
解题分析:
此题主要用到了扫描线的思想,现将各个矩形的横坐标离散化,然后用它们离散化后的横坐标(相当于将矩形的每条竖线投影在x轴上,然后将它们从0~n-1标号),并且利用这些标好的号建线段树,线段树的每个叶子节点表示离散化后的横坐标(比如从左往右数第一个叶子节点,它的区域表示的就是第0个竖线)。建好数后,就用扫描线从下至上进行扫描,若为下边界,则add[rt]+=1,若为上边界,则add[rt]-=1;扫描线到上面一个边界时,就用高度差*整个区域内的有效长度,即为这一部分矩形的面积。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; #define Lson rt<<1,l,mid
#define Rson rt<<1|1,mid+1,r //线段树的每一个节点都有对应的add和sum值
const int M =;
int add[M<<]; //add为区间标记,标记这段区间是否有效(是不是对求面积做出贡献的一段)
double sum[M<<],x[M<<]; //sum表示这段区间内总共的有效长度 struct node{
int cnt; //cnt=1为下边,cnt=-1为上边
double l,r,h; //分别记录线段的左端,右端和高度
node(){}
node(double a,double b,double c,int d):l(a),r(b),h(c),cnt(d){}
friend bool operator <(node tmp1,node tmp2){
return tmp1.h<tmp2.h; //从下往上扫,所以将h从小到大排序
}
}s[M<<];
void Pushup(int rt,int l,int r){
if(add[rt])sum[rt]=x[r+]-x[l]; //如果这段区域add不为0,则说明这段区域全部有效,由于原来查询的时候是左闭右开,所以这里的真实区域要+1
else if(l==r)sum[rt]=;
else sum[rt]=sum[rt<<]+sum[rt<<|]; //求出这段区域的真正有效长度
}
void update(int rt,int l,int r,int L,int R,int cor){
if(L<=l&&r<=R){
add[rt]+=cor;
Pushup(rt,l,r); //由于add标记改变了,所以更新一下tr[rt]的sum值
return;
}
int mid=(l+r)>>;
if(L<=mid)update(Lson,L,R,cor);
if(R>mid)update(Rson,L,R,cor);
Pushup(rt,l,r); //用递归更新一下路径上的所有sum值
} int main(){
int n,ncase=;
while(scanf("%d",&n)!=EOF,n){
double a,b,c,d;
int m=;
for(int i=;i<n;i++){
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
x[m]=a;
s[m++]=node(a,c,b,); //矩形下面那条边
x[m]=c;
s[m++]=node(a,c,d,-);
}
sort(x,x+m);
sort(s,s+m);
memset(add,,sizeof(add)); //这两个memset相当于建树
memset(sum,,sizeof(sum));
int k=;
for(int i=;i<m;i++){
if(x[i]!=x[i-]){
x[k++]=x[i]; //去重
}
}
//0~k-1为离散化后的线段树sum[1]所对应的区域
double ans=;
for(int i=;i<m-;i++){ //这里只需要循环m-1次就行,因为一共有m-1段面积
int l=lower_bound(x,x+k,s[i].l)-x;
int r=lower_bound(x,x+k,s[i].r)-x-; //为避免边的边界重复,我们选取左闭右开区间,所以r要减1
update(,,k-,l,r,s[i].cnt);
ans+=sum[]*(s[i+].h-s[i].h); //sum[1]代表 X(min)~X(max)区域内的有效线段长度,即需要乘以高度差的线段长度
}
printf("Test case #%d\n", ++ncase);
printf("Total explored area: %.2lf\n\n", ans);
}
return ;
}
2018-07-25
HDU 1542 矩形面积并【离散化+线段树+扫描线】的更多相关文章
- POJ 1151 Atlantis 矩形面积求交/线段树扫描线
Atlantis 题目连接 http://poj.org/problem?id=1151 Description here are several ancient Greek texts that c ...
- 51nod 1206 Picture 矩形周长求并 | 线段树 扫描线
51nod 1206 Picture 矩形周长求并 | 线段树 扫描线 #include <cstdio> #include <cmath> #include <cstr ...
- HDU 4419 Colourful Rectangle --离散化+线段树扫描线
题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何 ...
- 【HDU 1542】Atlantis 矩形面积并(线段树,扫描法)
[题目] Atlantis Problem Description There are several ancient Greek texts that contain descriptions of ...
- hdu1542 矩形面积并(线段树+离散化+扫描线)
题意: 给你n个矩形,输入每个矩形的左上角坐标和右下角坐标. 然后求矩形的总面积.(矩形可能相交). 题解: 前言: 先说说做这道题的感受: 刚看到这道题顿时就懵逼了,几何 烂的渣渣.后来从网上搜题解 ...
- ZOJ 2301 / HDU 1199 Color the Ball 离散化+线段树区间连续最大和
题意:给你n个球排成一行,初始都为黑色,现在给一些操作(L,R,color),给[L,R]区间内的求染上颜色color,'w'为白,'b'为黑.问最后最长的白色区间的起点和终点的位置. 解法:先离散化 ...
- hdu 1199 Color the Ball(离散化线段树)
Color the Ball Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) T ...
- POJ1177 Picture —— 求矩形并的周长 线段树 + 扫描线 + 离散化
题目链接:https://vjudge.net/problem/POJ-1177 A number of rectangular posters, photographs and other pict ...
- HDU 1542 矩形面积并
推荐阅读这篇文章 这里仅根据上述文章进行一些补充.主要是注意这里线段树点的意义变成了“边”.比如+-----+-----+,看作3个点abc和两条边e1和e2,那么线段树中点a代表e1,点b代表e2. ...
随机推荐
- luogu P4162 [SCOI2009]最长距离
传送门 可以枚举两个点然后计算答案,至于是否合法,就要看可不可以通过移不超过\(t\)个箱子使得两点连通,也可以看做找一条路径使得路径上的1个数不超过\(t\) 所以可以考虑最短路,相邻的点两两连边, ...
- vue学习之用 Vue.js + Vue Router 创建单页应用的几个步骤
通过vue学习一:新建或打开vue项目,创建好项目后,接下来的操作为: src目录重新规划——>新建几个页面——>配置这几个页面的路由——>给根实例注入路由配置 src目录重整 在项 ...
- mysql外键(FOREIGNKEY)使用介绍
原文地址:http://www.2cto.com/database/201501/367791.html 一.基本概念 1.MySQL中“键”和“索引”的定义相同,所以外键和主键一样也是索引的一种.不 ...
- 公共模块定义/草案(Common Module Definition / draft - CMD草案)
This specification addresses how modules should be written in order to be interoperable in browser-b ...
- Responsive响应式设计
在IE6-8中完全是不支持CSS3 Media Queries的.那么为了让IE6-8支持,我们就很有必要的在IE9以下的浏览器中加上media-queries.js或者respond.js脚本: & ...
- shiroWeb项目-登陆与退出实现(九)
原理 使用FormAuthenticationFilter过虑器实现 ,原理如下: 将用户没有认证时,请求loginurl进行认证,用户身份和用户密码提交数据到loginurl FormAuthent ...
- manjaro 的配置
一.更新源的配置: 1).自动方法: 在 终端 执行下面的命令从官方的源列表中对中国源进行测速和设置 sudo pacman-mirrors -c China 2).手动方法 自动方法(上面的方法1, ...
- linux 平台core dump文件生成
1. 在终端中输入ulimit -c 如果结果为0,说明当程序崩溃时,系统并不能生成core dump. root@hbg:/# ulimit -c0root@hbg:/# 2.使用ulimit -c ...
- Android天气预报
Android天气预报 1.指定 WebService 的命名空间和调用方法import org.ksoap2.serialization.SoapObject;private static fina ...
- PYTHON-有参装饰器,无参装饰器,语法糖
装饰器 装饰器就是闭包函数的一种应用场景 一 为何要用装饰器 #开放封闭原则:对修改封闭,对扩展开放 二 什么是装饰器 装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象. 强 ...