Atlantis poj1151 线段树扫描线

题意

题目给了n个矩形,每个矩形给了左下角右上角的坐标,矩形可能会重叠,求的是矩形最后的面积。

题解思路

这个是我线段树扫描线的第一题,听了学长的讲解,仔细研读了学长的代码,也算初步入门。

这里我们竖着的扫描线,从左到右来进行扫描的。

线段树这里端点代表的是一个区间

这里的y范围比较大,所以咱们需要离散化。

代码实现

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define mid ((tre[rt].l+tre[rt].r)>>1)
#define ls (rt<<1)
#define rs (rt<<1|1)
using namespace std;
const int maxn=1e2+7;
struct node{ //四元组
double x, y1, y2;
int k; //左边的边k是1, 右边的k为-1
bool friend operator < (node a, node b)
{
return a.x < b.x;
}
}a[maxn<<1]; struct tree{
int l, r, cnt; //cnt记录区间被标记的次数
double len;
}tre[maxn<<3]; map<double, int> mp;
double raw[maxn<<1];
int n,num; void build(int rt, int l, int r)
{
tre[rt].l=l;
tre[rt].r=r;
tre[rt].len=tre[rt].cnt=0;
if(l==r) return ;
build(ls, l, mid);
build(rs, mid+1, r);
} void change(int rt, int l, int r, int k)
{
if(l <= tre[rt].l && tre[rt].r <= r)
{
tre[rt].cnt+=k;
if(tre[rt].cnt>0)
{
tre[rt].len=raw[tre[rt].r+1] - raw[tre[rt].l];
}
else if(tre[rt].l==tre[rt].r) //到达端点了
{
tre[rt].len=0;
}
else tre[rt].len=tre[ls].len+tre[rs].len; return ;
}
if(l <= mid) change(ls, l, r, k);
if(r > mid) change(rs, l, r, k);
tre[rt].len = tre[rt].cnt > 0 ? raw[tre[rt].r+1] - raw[tre[rt].l] : tre[ls].len+tre[rs].len;
} int main()
{
while(scanf("%d", &n) && n)
{
int cnt;
double x1, y1, x2, y2;
for(int i=1; i<=n; i++)
{
cnt=i<<1;
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
a[cnt-1].x=x1; a[cnt-1].y1=y1; a[cnt-1].y2=y2; a[cnt-1].k=1;
a[cnt].x=x2; a[cnt].y1=y1; a[cnt].y2=y2; a[cnt].k=-1;
raw[cnt-1]=y1; raw[cnt]=y2;
}
n<<=1;
sort(raw+1, raw+1+n);
int m=unique(raw+1, raw+n+1)-(raw+1);
for(int i=1; i<=m; i++)
{
mp[raw[i]]=i;
}
sort(a+1, a+n+1);
build(1, 1, m-1); //这里线段树的点记录的区域,因为有m个y,所以就相当于m-1个区域
double ans=0;
for(int i=1; i<n; i++) //只需要处理到倒数第二个点即可
{
int l=mp[a[i].y1], r=mp[a[i].y2]-1;
change(1, l, r, a[i].k);
ans += tre[1].len*(a[i+1].x - a[i].x);
}
printf("Test case #%d\nTotal explored area: %.2f\n\n", ++num, ans);
}
return 0;
}

最新文章

  1. Linux常用命令学习7---(磁盘管理df du、磁盘的分区和格式化fdisk parted)
  2. 我JSP学习心得1
  3. webstorm常用快捷键(常用)
  4. 【转】编写更好的CSS代码
  5. js停止冒泡和阻止浏览器默认行为
  6. IntelliJ IDEA以不同格式导出数据库的数据
  7. HTML5 drag &amp; drop 拖拽与拖放简介
  8. hdu 4542 小明系列故事——未知剩余系
  9. HTML5移动开发中的input输入框类型
  10. LeeCode-Contains Duplicate
  11. 使用Freemarker创建word文档
  12. 纯javascript实现可拖住/大小的div
  13. python flask 如何修改默认端口号
  14. 【轻松前端之旅】CSS入门
  15. 通过JDOM实现XML与String的相互转换
  16. nginx location配置和rewrite写法
  17. 1-1 sacc(scss)入门
  18. ECS Navicat for MySQL远程连接报10038的错误
  19. 如何查看nginx的版本及配置选项?nginx都配置了哪些的模块?
  20. ios 点击失效、闪屏问题解决方案

热门文章

  1. python 删除/app/*/logs/*/*.logs指定多少天的文件
  2. 【Luogu4299】首都
  3. Arduino-LiquidCrystal_I2C 液晶库
  4. HDU-6703 array
  5. python新动态执行 文件头标识 禁止断言
  6. Spring Cloud架构教程 (四)服务网关(路由配置)
  7. Oracle In子句
  8. Charles抓取手机https请求
  9. Java 静态static 关键字作用
  10. yum命令查询详解