扫描线 + 线段树 : 求矩形面积的并 ---- hnu : 12884 Area Coverage
|
Mean:
在二维平面中,给你一些矩形的左下坐标(x1,y1)和右上坐标(x2,y2),让你求这些矩形面积的并。
analyse:
我们在y轴方向上维护一棵线段树。该线段树的模型是区间覆盖,即应该对像某个区间有没有被覆盖这样的查询,以及添加覆盖和删除覆盖这样的操作---也就是将矩形的左右两边界看作对y轴的覆盖来处理。我们将所有矩形的左右边界按照x坐标升序排序。每个矩形的左边界执行对y轴的覆盖操作,右边界执行对x轴的删除覆盖操作。
每次插入一条线段的时候,我们判断cover值(覆盖的次数),如果>0那么就算面积。
如图:

初始时每条线段的cover都为0;
线段1插入后,所对应的区间cover变为1,当第二条线段插入时,我们先判断一下该区间上的cover值,发现有一段cover是大于0的,所以就将对应的面积(蓝色部分)加入ans中,此时线段2下半部分的cover值变为2,上部分的cover值变为1,还要把线段1的上部分的x坐标更新为线段2的x值;
当第三条直线插入时,同样的道理,加入的是黄色部分的面积;第四条进入时,加入的是紫色部分的面积。
这样,我们只需要在插入前先计算面积,当所有线段插入结束,answer也就出来了。
所以我们的线段树只需要两个函数:build和insert函数。
Time complexity:O(n*logn)
Source code:
* this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-07-23-20.40
* Time: 0MS
* Memory: 137KB
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define LL long long
#define ULL unsigned long long
using namespace std;
const int N = ;
double y[ * N];
struct LINE
{
double x, y_down, y_up;
int flag;//左线段or右线段
};
LINE line[N << ];
struct Tree
{
int x;
int cover; // 覆盖次数
bool flag; // 是否为叶子节点
int y_up, y_down;
};
Tree tree[( << ) * ];
bool cmp( LINE a, LINE b )
{
return a.x < b.x;
}
void build( int l, int r, int x )
{
tree[x].x = -; //-1表示该区间没有线段
tree[x].cover = ;
tree[x].flag = false;
tree[x].y_up = y[r];
tree[x].y_down = y[l];
if( l + == r ) // 叶子结点: (1,2) (2,3) (3,4) (4,5)....
{
tree[x].flag = true;
return;
}
int tmp = x << ;
int mid = ( l + r ) >> ;
build( l, mid, tmp );
build( mid, r, tmp + );;
}
double insert( int i, double x, double l, double r, int flag )
{
if( r <= tree[i].y_down || l >= tree[i].y_up ) //要插入的线段不在该区间
return ;
if( tree[i].flag ) //叶子节点
{
if( tree[i].cover > ) // 需要求并面积
{
double temp_x = tree[i].x;
double ans = ( x - temp_x ) * ( tree[i].y_up - tree[i].y_down ); // 宽*高
tree[i].x = x; // 更新树中的x值
tree[i].cover += flag;
return ans;
}
else
{
tree[i].cover += flag;
tree[i].x = x;
return ;
}
}
double ans1, ans2;
int tmp = i << ;
ans1 = insert( tmp, x, l, r, flag );
ans2 = insert( tmp + , x, l, r, flag );
return ans1 + ans2;
}
int main()
{
ios_base::sync_with_stdio( false );
cin.tie( );
int T;
cin >> T;
double x1, y1, x2, y2;
while( T-- )
{
int n;
cin >> n;
int index = ;
for( int i = ; i <= n; i++ )
{
scanf( "%lf %lf %lf %lf", &x1, &y1, &x2, &y2 );
y[index] = y1;
line[index].x = x1;
line[index].y_down = y1;
line[index].y_up = y2;
line[index].flag = ;
index++;
y[index] = y2;
line[index].x = x2;
line[index].y_down = y1;
line[index].y_up = y2;
line[index].flag = -;
index++;
}
index--;
double ans = 0.0;
sort( line + , line + + index, cmp );
sort( y + , y + + index );
build( , index, );
for( int i = ; i <= index; i++ )
{
ans += insert( , line[i].x, line[i].y_down, line[i].y_up, line[i].flag );
}
printf( "%.0lf\n", ans );
}
return ;
}
扫描线 + 线段树 : 求矩形面积的并 ---- hnu : 12884 Area Coverage的更多相关文章
- POJ 1151Atlantis 扫描线+线段树求矩形面积并
题目链接 #include <iostream> #include <vector> #include <cstdio> #include <cstring& ...
- HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)
链接:线段树求矩形面积并 扫描线+离散化 1.给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 2.看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同. 求面积时,用被覆 ...
- 【hdu1542】线段树求矩形面积并
分割线内容转载自http://hzwer.com/879.html ------------------------------------------------------------------ ...
- POJ 1151 / HDU 1542 Atlantis 线段树求矩形面积并
题意:给出矩形两对角点坐标,求矩形面积并. 解法:线段树+离散化. 每加入一个矩形,将两个y值加入yy数组以待离散化,将左边界cover值置为1,右边界置为2,离散后建立的线段树其实是以y值建的树,线 ...
- POJ 1151 Atlantis 线段树求矩形面积并 方法详解
第一次做线段树扫描法的题,网搜各种讲解,发现大多数都讲得太过简洁,不是太容易理解.所以自己打算写一个详细的.看完必会o(∩_∩)o 顾名思义,扫描法就是用一根想象中的线扫过所有矩形,在写代码的过程中, ...
- 【hdu1255】线段树求矩形面积交
题意大概就是上图这个样子.<=100组测试数据,每组<=1000个矩形. 题解: 这个问题怎么解决..做了上一题矩形面积并应该就会了.. 对于每个节点维护3个值: cnt:该节点所代表的这 ...
- HDU 1255 覆盖的面积 (扫描线 线段树 离散化 矩形面积并)
题目链接 题意:中文题意. 分析:纯手敲,与上一道题目很相似,但是刚开始我以为只是把cnt>=0改成cnt>=2就行了,. 但是后来发现当当前加入的线段的范围之前 还有线段的时候就不行了, ...
- UVA 11983 Weird Advertisement --线段树求矩形问题
题意:给出n个矩形,求矩形中被覆盖K次以上的面积的和. 解法:整体与求矩形面积并差不多,不过在更新pushup改变len的时候,要有一层循环,来更新tree[rt].len[i],其中tree[rt] ...
- HDU 1542.Atlantis-线段树求矩形面积并(离散化、扫描线/线段树)-贴模板
好久没写过博客了,这学期不是很有热情去写博客,写过的题也懒得写题解.现在来水一水博客,写一下若干年前的题目的题解. Atlantis Time Limit: 2000/1000 MS (Java/Ot ...
随机推荐
- UWP滑动后退
经过近些年智能手机App的不断发展,用户已经不仅仅满足于功能上的需求.UI.设计等非功能点逐渐在App体验中占了大多数的分数.不知从何时起,滑动手势就成为了App的一个标配.他不仅仅是一个功能,更是一 ...
- java提高篇(十五)-----关键字final
在程序设计中,我们有时可能希望某些数据是不能够改变的,这个时候final就有用武之地了.final是java的关键字,它所表示的是“这部分是无法修改的”.不想被改变的原因有两个:效率.设计.使用到fi ...
- [Beautifulzzzz的博客目录] 快速索引点这儿O(∩_∩)O~~,红色标记的是不错的(⊙o⊙)哦~
3D相关开发 [direct-X] 1.direct-X最小框架 [OpenGL] 1.环境搭建及最小系统 [OpenGL] 2.企业版VC6.0自带的Win32-OpenGL工程浅析 51单片机 [ ...
- sonne_game网站开发02spring+mybatis框架搭建
从最开始搭框架谈起,而且,我不仅仅会讲how,还会努力讲why.因为对于web开发,由于有太多好的框架.组件.工具,使得how往往不是那么深刻,背后的why更值得专研.如果有初学者关注我这个系列,也一 ...
- Java使用snakeyaml解析yaml
YAML Yaml是一种"是一个可读性高并且容易被人类阅读,容易和脚本语言交互,用来表达资料序列的编程语言."类似于XML但比XML更简洁,语法详见 http://www.ruan ...
- Thrift架构~从图中理解thrift,它事实上是一种远程过程调用
thrift为我们简化了tcp通讯,它可以使用我们方便的建立各种语言的服务端与客户端,并实现客户端对服务器的远程过程调用,简单的说就是服务器通过thrift架构对外开放一些接口,并自己实现这些接口,如 ...
- getattribute()与getparameter()的区别
1.它们取到的值不同.getAttribute取到的是对象(object),而getParameter取到的是String. 2.数据传递路劲不同.request.getParameter方法传递的数 ...
- 理解 Lua 的那些坑爹特性
按:最近看到了依云的文章,一方面,为Lua被人误解而感到十分难过,另一方面,也为我的好友, 依云没有能够体会到Lua的绝妙和优雅之处而感到很遗憾,因此我写了这篇文章,逐条款地说明了 依云理解中出现的一 ...
- MSSQL Server数据库的四种连接方法和sql连接字符串
MSSQL Server数据库的四种连接方法和sql连接字符串 分类: [ 03 ] C#(131) [ 07 ] SQL Server(68) [ 01 ] .NET(189) 今天用SQL Ser ...
- 快速入门系列--MySQL
一直说要好好复习一下Mysql都木有时间,终于赶上最近新购买了阿里云,决定使用CentOS去试试.NET Core等相关的开发,于是决定好好的回顾下这部分知识,由于Mysql的数据库引擎是插件式的,对 ...