POJ1151 Atlantis 线段树+扫描线(离散化)
来源:互联网 发布:javascript dom是什么 编辑:程序博客网 时间:2024/05/17 21:59
题目链接:http://poj.org/problem?id=1151
题目大意:给你一些矩形,其顶点坐标是浮点数,可能相互重叠,问这些矩形覆盖到的面积是多少。
分析:我们将Y轴进行离散化,n个矩形的2n条边界,最多可将Y轴分成2n-1个区域,我们对这些区间进行编号,建立线段树。
const int M=210;struct segment{ int l,r; double len; //表示区间上有多长的部分是落在矩形中的 int cov; //该区间当前被多少个矩形完全包含 int mid() { return (l+r)>>1; }}tree[M<<2];
将矩形的纵边从左到右排序,然后依次将这些纵边插入线段树,要记住哪些纵边是矩形的左边界(始边),哪些是右边界(终边),以便插入时,对len和cov做不同的修改。插入一条边后,就根据根结点的len值增加总覆盖面积area的值:area+=len*(该边到下一条边的距离)。
实现代码如下:
#include <cstdio>#include <algorithm>#include <iostream>using namespace std;const int M=210;struct segment{ int l,r; double len; //表示区间上有多长的部分是落在矩形中的 int cov; //该区间当前被多少个矩形完全包含 int mid() { return (l+r)>>1; }}tree[M<<2];struct Line{ double x,y1,y2; bool bleft; //标记该线段是否为矩形的左边 bool operator <(const Line &a) const { return x<a.x; }}line[M];double y[M]; //记录所有矩形的y坐标void build(int rt,int l,int r){ tree[rt].l=l; tree[rt].r=r; tree[rt].len=0; tree[rt].cov=0; if(l==r) return ; int m=tree[rt].mid(); build(rt<<1,l,m); build(rt<<1|1,m+1,r);}void update(int rt,int l,int r,bool op){ if(tree[rt].l==l&&tree[rt].r==r) { if(op) {//当前边是矩形的左边界的话,在该区间插入矩形左边的一部分或者全部,覆盖区间[l,r] tree[rt].len=y[r+1]-y[l]; tree[rt].cov++; } else { tree[rt].cov--; if(tree[rt].cov==0) { if(tree[rt].l==tree[rt].r) tree[rt].len=0; else tree[rt].len=tree[rt<<1].len+tree[rt<<1|1].len; } } return ; } int m=tree[rt].mid(); if(r<=m) update(rt<<1,l,r,op); else if(l>m) update(rt<<1|1,l,r,op); else { update(rt<<1,l,m,op); update(rt<<1|1,m+1,r,op); } if(tree[rt].cov==0) //如果不为0,说明该区间当前仍然被某个矩形完全包含,此时不更新len值 tree[rt].len=tree[rt<<1].len+tree[rt<<1|1].len;}int main(){ int n,T=1; while(scanf("%d",&n)&&n) { int yc=0,lc=0; //y[]和line[]的计数器 for(int i=0;i<n;i++) { double x1,y1,x2,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); y[yc++]=y1; y[yc++]=y2; line[lc].x=x1; line[lc].y1=y1; line[lc].y2=y2; line[lc].bleft=true; lc++; line[lc].x=x2; line[lc].y1=y1; line[lc].y2=y2; line[lc].bleft=false; lc++; } sort(y,y+yc); yc=unique(y,y+yc)-y; //排序并去重 build(1,0,yc); sort(line,line+lc); double area=0; for(int i=0;i<lc-1;i++) //插入每条边 { int l=lower_bound(y,y+yc,line[i].y1)-y; //二分找出当前边离散化后对应的线段树的区间端点 int r=lower_bound(y,y+yc,line[i].y2)-y; update(1,l,r-1,line[i].bleft); area+=tree[1].len*(line[i+1].x-line[i].x); } printf("Test case #%d\nTotal explored area: %.2f\n\n",T++,area); } return 0;}
0 0
- poj1151 & hdu1542 Atlantis(扫描线+离散化+线段树)
- poj1151 Atlantis(线段树+离散化+扫描线)
- POJ1151 Atlantis 线段树+扫描线(离散化)
- poj1151 Atlantis 扫描线+线段树+离散化
- poj1151-- Atlantis(线段树+离散化+扫描线)
- 【POJ1151】Atlantis-线段树+离散化+扫描线
- POJ1151--Atlantis(离散化+扫描线)
- POJ1151 Atlantis(线段树,扫描线,离散化,矩形面积并)
- [POJ1151]Atlantis(扫描线+线段树)
- 线段树+扫描线+离散化解poj1151 hdu 1542 ( Atlantis )
- POJ1151 (HDU 1542) Atlantis【矩形面积并,线段树+离散化+扫描线模板】
- poj1151 Atlantis(线段树+扫描线+离散化,求矩形面积并)
- poj1151——Atlantis(离散化+扫描线)
- Atlantis poj1151 扫描线+线段树
- poj1151 Atlantis(线段树+扫描线)
- poj1151-Atlantis(线段树+扫描线(经典题))
- Atlantis(扫描线+线段树+离散化)
- HDU 1542 Atlantis(线段树+离散化+扫描线)
- 过滤器实现强制登录
- andriod studio 混淆代码
- PhpStorm的序列号和证书
- 发送普通文本和超文本邮件,并且把携带的附件显示在超文本文件中
- 海量数据处理:十道面试题与十个海量数据处理方法总结
- POJ1151 Atlantis 线段树+扫描线(离散化)
- 点击表格,高亮,JS代码
- 上班以来的第一个稍大的任务
- GCD
- grep awk sed
- 托福阅读中的五种复习方法【zhasite】
- malloc.c
- Feature分支
- 异步调用与多线程的区别