hdu1542 线段树扫描线求矩形面积的并
题意:
给你n个正方形,求出他们的所占面积有多大,重叠的部分只能算一次。
思路:
自己的第一道线段树扫描线题目,至于扫描线,最近会写一个总结,现在就不直接在这里写了,说下我的方法,我是离散化横坐标,然后去扫描纵坐标(反过来也行),把每一个长方形的两个宽边拿出来,按照高度排序,然后开始扫描,对于么一个区间的更新,我用的是暴力点更新,因为如果写段更新的话第二个权值没有想到什么好的一起更新的方法。
然后在做另一道题目的时候发现这个方法超时了,没办法又去硬着头皮学了段更新的,段更新的扫描线应该大体有两种,我学了其中一个,然后又用段更新的做了下这个题目。
一开始的暴力区间扫描
#include<stdio.h>
#include<string.h>
#include<algorithm> #define lson l ,mid ,t << 1
#define rson mid + 1 ,r ,t <<1 | 1
using namespace std; typedef struct
{
double l ,r ,h;
int mk;
}EDGE; EDGE edge[100*2+10];
double sum[100*2*4+10];
double tmp[100*2+10];
double num[100*2+10];
int now[100*2+10]; bool camp(EDGE a ,EDGE b)
{
return a.h < b.h;
} void Pushup(int t)
{
sum[t] = sum[t<<1] + sum[t<<1|1];
} void Update(int l ,int r ,int t ,int a ,int b)
{
if(l == r)
{
now[a] += b;
if(now[a]) sum[t] = num[a+1] - num[a];
else sum[t] = 0;
return;
}
int mid = (l + r) >> 1;
if(a <= mid) Update(lson ,a ,b);
else Update(rson ,a ,b);
Pushup(t);
} int search_2(int n ,double now)
{
int low ,up ,mid ,ans;
low = 0 ,up = n;
while(low <= up)
{
mid = (low + up) >> 1;
if(now <= num[mid])
{
ans = mid;
up = mid - 1;
}
else low = mid + 1;
}
return ans;
} int main ()
{
int n ,i ,j ,cas = 1;
double x1 ,x2 ,y1 ,y2;
while(~scanf("%d" ,&n) && n)
{
int id = 0;
for(i = 1 ;i <= n ;i ++)
{
scanf("%lf %lf %lf %lf" ,&x1 ,&y1 ,&x2 ,&y2);
edge[++id].l = x1;
edge[id].r = x2 ,edge[id].h = y1 ,edge[id].mk = 1;
tmp[id] = x1;
edge[++id].l = x1;
edge[id].r = x2 ,edge[id].h = y2 ,edge[id].mk = -1;
tmp[id] = x2;
}
sort(tmp + 1 ,tmp + id + 1);
sort(edge + 1 ,edge + id + 1 ,camp);
tmp[0] = -1;
for(id = 0 ,i = 1 ;i <= n * 2 ;i ++)
if(tmp[i] != tmp[i-1]) num[++id] = tmp[i];
memset(now ,0 ,sizeof(now));
memset(sum ,0 ,sizeof(sum));
double ans = 0;
edge[0].h = edge[1].h;
for(i = 1 ;i <= n * 2 ;i ++)
{
ans += sum[1] * (edge[i].h - edge[i-1].h);
int l = search_2(id ,edge[i].l);
int r = search_2(id ,edge[i].r) - 1;
for(j = l ;j <= r ;j ++)
Update(1 ,id - 1 ,1 ,j ,edge[i].mk);
}
printf("Test case #%d\n" ,cas ++);
printf("Total explored area: %.2lf\n\n" ,ans);
}
return 0;
}
后来的段更新扫描
#include<stdio.h>
#include<string.h>
#include<algorithm> #define lson l ,mid ,t << 1
#define rson mid , r ,t << 1 | 1
using namespace std; typedef struct
{
double l ,r ,h;
int mk;
}EDGE; EDGE edge[1000]; double len[1000];
double tmp[1000] ,num[1000];
int cnt[1000]; bool camp(EDGE a ,EDGE b)
{
return a.h < b.h;
} void Pushup(int l ,int r ,int t)
{
if(cnt[t]) len[t] = num[r] - num[l];
else if(l + 1 == r) len[t] = 0;
else len[t] = len[t<<1] + len[t<<1|1];
}
void Update(int l ,int r ,int t ,int a ,int b ,int c)
{
if(l == a && r == b)
{
cnt[t] += c;
Pushup(l ,r ,t);
return;
}
int 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);
} int search_2(int id ,double now)
{
int low ,up ,mid ,ans;
low = 1 ,up = id;
while(low <= up)
{
mid = (low + up) >> 1;
if(now <= num[mid])
{
ans = mid;
up = mid - 1;
}
else low = mid + 1;
}
return ans;
} int main ()
{
int id ,n ,i ,cas = 1;
double x1 ,x2 ,y1 ,y2;
while(~scanf("%d" ,&n) && n)
{
for(id = 0 ,i = 1 ;i <= n ;i ++)
{
scanf("%lf %lf %lf %lf" ,&x1 ,&y1 ,&x2 ,&y2);
edge[++id].l = x1;
edge[id].r = x2 ,edge[id].h = y1 ,edge[id].mk = 1;
tmp[id] = x1;
edge[++id].l = x1;
edge[id].r = x2 ,edge[id].h = y2 ,edge[id].mk = -1;
tmp[id] = x2;
}
sort(tmp + 1 ,tmp + id + 1);
sort(edge + 1 ,edge + id + 1 ,camp);
memset(len ,0 ,sizeof(len));
memset(cnt ,0 ,sizeof(cnt));
tmp[0] = -1;
for(id = 0 ,i = 1 ;i <= n * 2 ;i ++)
if(tmp[i] != tmp[i-1]) num[++id] = tmp[i];
double ans = 0;
edge[0].h = edge[1].h;
for(i = 1 ;i <= n * 2 ;i ++)
{
ans += len[1] * (edge[i].h - edge[i-1].h);
int l = search_2(id ,edge[i].l);
int r = search_2(id ,edge[i].r);
Update(1 ,id ,1 ,l ,r ,edge[i].mk);
}
printf("Test case #%d\n" ,cas ++);
printf("Total explored area: %.2lf\n\n" ,ans);
}
return 0;
}
hdu1542 线段树扫描线求矩形面积的并的更多相关文章
- 2015 UESTC 数据结构专题E题 秋实大哥与家 线段树扫描线求矩形面积交
E - 秋实大哥与家 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/59 De ...
- HDU 1542"Atlantis"(线段树+扫描线求矩形面积并)
传送门 •题意 给你 n 矩形,每个矩形给出你 $(x_1,y_1),(x_2,y_2)$ 分别表示这个矩形的左下角和右上角坐标: 让你求这 n 个矩形并的面积: 其中 $x \leq 10^{5} ...
- hdu1828 线段树扫描线求矩形面积的周长
题意: 给你n个矩形,问你这n个矩形所围成的图形的周长是多少. 思路: 线段树的扫描线简单应用,这个题目我用的方法比较笨,就是扫描两次,上下扫描,求出多边形的上下边长和,然后同 ...
- hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- HDU 1828“Picture”(线段树+扫描线求矩形周长并)
传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...
- POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]
题意:求矩形面积并 分析:使用线段树+扫描线...因为坐标是浮点数的,因此还需要离散化! 把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用col表示该区间有多少个下边,sum代表该区 ...
- 扫描线 + 线段树 : 求矩形面积的并 ---- hnu : 12884 Area Coverage
Area Coverage Time Limit: 10000ms, Special Time Limit:2500ms, Memory Limit:65536KB Total submit user ...
- UVA-11983-Weird Advertisement(线段树+扫描线)[求矩形覆盖K次以上的面积]
题意: 求矩形覆盖K次以上的面积 分析: k很小,可以开K颗线段树,用sum[rt][i]来保存覆盖i次的区间和,K次以上全算K次 // File Name: 11983.cpp // Author: ...
- hdu 4419 线段树 扫描线 离散化 矩形面积
//离散化 + 扫描线 + 线段树 //这个线段树跟平常不太一样的地方在于记录了区间两个信息,len[i]表示颜色为i的被覆盖的长度为len[i], num[i]表示颜色i 『完全』覆盖了该区间几层. ...
随机推荐
- HDOJ-1069(动态规划+排序+嵌套矩形问题)
Monkey and Banana HDOJ-1069 这里实际是嵌套矩形问题的变式,也就是求不固定起点的最长路径 动态转移方程为:dp[i]=max(dp[j]+block[i].h|(i,j)∈m ...
- ASP.NET如何把ASPX网站部署到IIS上
当一个项目完成了,你是否想过把它发布到服务器上去呢?那么下面就来告诉你如何去部署它吧! (Visual Studio版本: 2019) 首先要准备好你的项目 然后进行如下操作 第一大步骤 1.打开你需 ...
- 用c++解一元二次方程
解方程 github项目地址 这两天得知初二的表妹学了一元二次方程,听说还不会解,我就想着试试用C语言编写解方程. 一元二次方程 用公式法 这种方法效果很好: #include"funct. ...
- ZooKeeper 的选举机制,你了解多少?
本文作者:HelloGitHub-老荀 Hi,这里是 HelloGitHub 推出的 HelloZooKeeper 系列,免费开源.有趣.入门级的 ZooKeeper 教程,面向有编程基础的新手. 项 ...
- WPF 基础 - Window 启动动画
<Window ... WindowStyle="None" AllowsTransparency="True" RenderTransformOrigi ...
- Spring Boot 启动过程
一切从SpringApplication.run()开始,最终返回一个ConfigurableApplicationContext 构造了一个SpringApplication对象,然后调用它的run ...
- Python-生成器
创建生成器 创建生成器需要两部步骤 定义一个包含yield语句的函数 调用第一步创建的函数得到生成器 def test(val,step): 2 print("函数开始执行") 3 ...
- 攻防世界 reverse Mysterious
Mysterious BUUCTF-2019 int __stdcall sub_401090(HWND hWnd, int a2, int a3, int a4) { char v5; // [e ...
- 一种3位sar adc工作过程推导(二)
3位sar adc采用下图的电容阵列,需要23个电容,它的基本单元有二进制加权的电容阵列.1个与LSB电容等值的电容:它利用电容上的初始电荷再分配完成二进制搜索算法,因此功耗一般比较小,而且不需要额外 ...
- 国产mcu理论数据评估工作记录
目录 前言 简要工作记录 前言 时间:20210315 主要记录这两天对国内各IC厂商的 MCU 了解记录. 大环境,ST 厂商 MCU 疯狂涨价,国内 MCU 也越来越完善,还便宜.同时,全球缺晶圆 ...