hdu 3265 线段树扫描线(拆分矩形)
题意:
给你n个矩形,每个矩形上都有一个矩形的空洞,所有的矩形都是平行于x,y轴的,最后问所有矩形的覆盖面积是多少。
思路:
是典型的矩形覆盖问题,只不过每个矩形上多了一个矩形洞,我的做法是吧当前的矩形分成四个小的矩形,然后用线段树的扫描线扫一遍就ok了,记得要用INT64 ,自己没注意这个问题wa了一次。
#include<stdio.h>
#include<string.h>
#include<algorithm> #define N 300000
#define lson l ,mid ,t << 1
#define rson mid ,r ,t << 1 | 1
using namespace std; typedef struct
{
__int64 l ,r ,h ,mk;
}EDGE; __int64 len[N] ,cnt[N];
EDGE edge[N*2]; bool camp(EDGE a ,EDGE b)
{
return a.h < b.h || a.h == b.h && a.mk > b.mk;
} void Pushup(__int64 l ,__int64 r ,__int64 t)
{
if(cnt[t]) len[t] = r - l;
else if(l + 1 == r) len[t] = 0;
else len[t] = len[t<<1] + len[t<<1|1];
} void Update(__int64 l ,__int64 r ,__int64 t ,__int64 a ,__int64 b ,__int64 c)
{
//printf("%d %d %d\n" ,l ,r ,t);
if(l == a && r == b)
{
cnt[t] += c;
Pushup(l ,r ,t);
return;
}
__int64 mid = (l + r) >> 1;
if(b <= mid) Update(lson ,a ,b ,c);
else if(a >= mid) Update(rson ,a ,b ,c);
else
{
Update(lson ,a ,mid ,c);
Update(rson ,mid ,b ,c);
}
Pushup(l ,r ,t);
} __int64 abss(__int64 x)
{
return x < 0 ? -x : x;
} int main ()
{
__int64 i ,j ,n ,x1 ,x2 ,x3 ,x4 ,y1 ,y2 ,y3 ,y4 ,id;
__int64 xx1 ,xx2 ,yy1 ,yy2;
while(~scanf("%I64d" ,&n) && n)
{
for(id = 0 ,i = 1 ;i <= n ;i ++)
{
scanf("%I64d %I64d %I64d %I64d %I64d %I64d %I64d %I64d" ,&x1 ,&y1 ,&x2 ,&y2 ,&x3 ,&y3 ,&x4 ,&y4);
x1 ++ ,y1 ++ ,x2 ++ ,y2 ++ ,x3 ++ ,y3 ++ ,x4 ++ ,y4 ++;
// x1 y2 x2 y4
xx1 = x1 ,xx2 = x2 ,yy1 = y2 ,yy2 = y4;
if(abss(xx1 - xx2) && abss(yy1 - yy2))
{
edge[++id].l = xx1;
edge[id].r = xx2 ,edge[id].h = yy1 ,edge[id].mk = 1; edge[++id].l = xx1;
edge[id].r = xx2 ,edge[id].h = yy2 ,edge[id].mk = -1;
}
// x1 y3 x2 y1
xx1 = x1 ,xx2 = x2 ,yy1 = y3 ,yy2 = y1;
if(abss(xx1 - xx2) && abss(yy1 - yy2))
{
edge[++id].l = xx1;
edge[id].r = xx2 ,edge[id].h = yy1 ,edge[id].mk = 1; edge[++id].l = xx1;
edge[id].r = xx2 ,edge[id].h = yy2 ,edge[id].mk = -1;
} // x1 y4 x3 y3
xx1 = x1 ,xx2 = x3 ,yy1 = y4 ,yy2 = y3;
if(abss(xx1 - xx2) && abss(yy1 - yy2))
{
edge[++id].l = xx1;
edge[id].r = xx2 ,edge[id].h = yy1 ,edge[id].mk = 1; edge[++id].l = xx1;
edge[id].r = xx2 ,edge[id].h = yy2 ,edge[id].mk = -1;
} // x4 y4 x2 y3
xx1 = x4 ,xx2 = x2 ,yy1 = y4 ,yy2 = y3;
if(abss(xx1 - xx2) && abss(yy1 - yy2))
{
edge[++id].l = xx1;
edge[id].r = xx2 ,edge[id].h = yy1 ,edge[id].mk = 1; edge[++id].l = xx1;
edge[id].r = xx2 ,edge[id].h = yy2 ,edge[id].mk = -1;
}
}
sort(edge + 1 ,edge + id + 1 ,camp);
__int64 Ans = 0;
memset(len ,0 ,sizeof(len));
memset(cnt ,0 ,sizeof(cnt));
edge[0].h = edge[1].h;
for(i = 1 ;i <= id ;i ++)
{
Ans += len[1] * (edge[i].h - edge[i-1].h);
Update(1 ,50001,1 ,edge[i].l ,edge[i].r ,edge[i].mk); }
printf("%I64d\n" ,Ans);
}
return 0;
}
hdu 3265 线段树扫描线(拆分矩形)的更多相关文章
- hdu 4419 线段树 扫描线 离散化 矩形面积
//离散化 + 扫描线 + 线段树 //这个线段树跟平常不太一样的地方在于记录了区间两个信息,len[i]表示颜色为i的被覆盖的长度为len[i], num[i]表示颜色i 『完全』覆盖了该区间几层. ...
- HDU 1828“Picture”(线段树+扫描线求矩形周长并)
传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...
- hdu 4052 线段树扫描线、奇特处理
Adding New Machine Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- hdu 1828 线段树扫描线(周长)
Picture Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]
题意:求矩形面积并 分析:使用线段树+扫描线...因为坐标是浮点数的,因此还需要离散化! 把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用col表示该区间有多少个下边,sum代表该区 ...
- hdu 5091(线段树+扫描线)
上海邀请赛的一道题目,看比赛时很多队伍水过去了,当时还想了好久却没有发现这题有什么水题的性质,原来是道成题. 最近学习了下线段树扫描线才发现确实是挺水的一道题. hdu5091 #include &l ...
- HDU 5107 线段树扫描线
给出N个点(x,y).每一个点有一个高度h 给出M次询问.问在(x,y)范围内第k小的高度是多少,没有输出-1 (k<=10) 线段树扫描线 首先离散化Y坐标,以Y坐标建立线段树 对全部的点和询 ...
- hdu1542 线段树扫描线求矩形面积的并
题意: 给你n个正方形,求出他们的所占面积有多大,重叠的部分只能算一次. 思路: 自己的第一道线段树扫描线题目,至于扫描线,最近会写一个总结,现在就不直接在这里写了,说下我的方 ...
- HDU 5091 线段树扫描线
给出N个点.和一个w*h的矩形 给出N个点的坐标,求该矩形最多能够覆盖多少个点 对每一个点point(x.y)右边生成相应的点(x+w,y)值为-1: 纵向建立线段树,从左到右扫描线扫一遍.遇到点则用 ...
随机推荐
- PAT-1064(Complete Binary Search Tree)JAVA实现
Complete Binary Search Tree PAT-1064 本次因为涉及到完全二叉排序树,所以可以使用数组的形式来存储二叉排序树 对输入序列排序后,得到的是中序遍历二叉排序树的序列.对这 ...
- SpringMVC-01 什么是SpringMVC
SpringMVC-01 什么是SpringMVC 回顾MVC 1.什么是MVC MVC是模型(Model).视图(View).控制器(Controller)的简写,是一种软件设计规范. 是将业务逻辑 ...
- 如何自学成 Python 大神?这里有些建议
人生苦短,我用 Python.为什么?简单明了的理由当然是开发效率高.但是学习 Python 的初学者往往会面临以下残酷的现状:网上充斥着大量的学习资源.书籍.视频教程和博客,但是大部分都是讲解基础知 ...
- DataFocus小学堂|客户分析之复活客户分析
复活客户分析 什么是"复活客户"?如何进行"复活客户分析"呢?今天,我们借助DataFocus系统,来了解一种简单的复活客户分析. 1.何为复活客户 复活客户, ...
- 冒泡算法及其优化(java)
冒泡算法的规则: 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放待排序序列的起始位置(或末尾位置),直到全部待排序的数据元素排完 动态图: 对应代码 static void swap(i ...
- pip安装更新模块,以及执行更新所有模块
moudle_name:是对应的模块名:请自行更换为自己需要更新的模块名 查看所有可更新的模块: pip list --outdated 更新某一个模块: pip install --upgrade ...
- P1049_装箱问题(JAVA语言)
思路:动态规划的背包问题.使箱子剩余空间最小,也就是使箱内装的物品体积达到最大,我们可将物品的体积视为价值,然后按照01背包问题求解即可. //直接上模板 题目描述 有一个箱子容量为VV(正整数,0 ...
- 操作系统实验(一)-Shell编程
操作系统实验:Shell编程 emmmmm,实验前老师发了一份实验说明,里面有教怎么配置虚拟机Ubuntu.这里就不做过多叙述,需要说明的是,kali和ubuntu都可以以shell运行这个C语言程序 ...
- VSCode中插件Code Spell Checker
说在前面 介绍 Code Spell Checker 是在VSCode中的一款插件,能够帮助我们检查单词拼写是否出现错误,检查的规则遵循 camelCase (驼峰拼写法). 安装方法 打开VSCod ...
- [Azure Devops] 使用 Azure Repos 管理代码
1. 什么是 Azure Repos Azure Repos 是一组版本控制工具,可用于管理代码.无论您的软件项目是大型项目还是小型项目,都应尽快使用版本控制. 版本控制系统是可帮助您跟踪随时间变化对 ...