【HDU 1542】Atlantis(线段树+离散化,矩形面积并)
求矩形面积并,离散化加线段树。
扫描线法:
用平行x轴的直线扫,每次ans+=(下一个高度-当前高度)*当前覆盖的宽度。
#include<algorithm>
#include<cstdio>
#include<cstring>
#define dd double
#define ll long long
#define N 201
using namespace std;
struct P{dd s,e,h;int f;}p[N];
struct Tree{dd sum;int c;}t[N<<];
dd a,b,c,d,x[N],ans;
int n,m,num;
int cmp(const P &a,const P &b){
return a.h<b.h;
}
void pushUp(ll rt,ll l,ll r){
if(t[rt].c)t[rt].sum=x[r+]-x[l];//r+1是因为节点[l,r]表示区间[x[l],x[r+1]]。
else if(l==r)t[rt].sum=;
else t[rt].sum=t[rt<<].sum+t[rt<<|].sum;
}
void update(ll s,ll e,ll rt,ll l,ll r,ll v){
if(s<=l&&r<=e) t[rt].c+=v;
else {
if(l>e||r<s)return;
ll m=l+r>>;
update(s,e,rt<<,l,m,v);
update(s,e,rt<<|,m+,r,v);
}
pushUp(rt,l,r);
}
int main()
{
while(scanf("%d",&n),n){
int k=;
for(int i=;i<n;i++){
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
x[++k]=a,p[k]=(P){a,c,b,};
x[++k]=c,p[k]=(P){a,c,d,-};
}
sort(x+,x++k);
sort(p+,p++k,cmp);
m=;
for(int i=;i<=k;i++)
if(x[i]!=x[i-])x[m++]=x[i];
ans=;
for(int i=;i<=k;i++){//共k条线段,每次计算p[i].h到p[i+1].h之间的面积,第k次相当于清空所有,酱就不用初始化线段树了。
int l=lower_bound(x,x+m,p[i].s)-x;
int r=lower_bound(x,x+m,p[i].e)-x-;//r-1同上原因
update(l,r,,,m-,p[i].f);
ans+=t[].sum*(p[i+].h-p[i].h);
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",++num,ans);
}
return ;
}
另一种方法还是线段树,这里扫描线用的是平行y轴的直线,每次增加的面积是当前扫描的竖线所在的高度区间的最后一次的x与当前x的差值乘上区间的高度。所以每次增加的不一定是一个矩形,而是多个矩形并。
#include<cstdio>
#include<algorithm>
#define dd double
using namespace std;
#define N 201
struct P{dd x,y1,y2;int f;}p[N];
struct TREE{dd y1,y2,x;int c,f;}tree[N<<];
dd x1,y1,x2,y2,y[N];
int n,k,num;
int cmp(const P &a,const P &b){
return a.x<b.x;
}
void build(int i,int l,int r){
tree[i].c=tree[i].f=;
tree[i].y1=y[l];//直接将线段树节点代表的区间存在线段树里
tree[i].y2=y[r];
if(l+==r){
tree[i].f=;
return;
}
int mk=(l+r)>>;
build(i<<,l,mk);
build(i<<|,mk,r);
}
dd insert(int i,dd x,dd l,dd r,int flag){
if(r<=tree[i].y1||l>=tree[i].y2)
return ;
if(tree[i].f){//离散后的一个最小区间,叶子节点
dd ans;
if(tree[i].c>)//全覆盖
ans=(x-tree[i].x)*(tree[i].y2-tree[i].y1);//(当前x-该区间最后的x)*区间高度
else
ans=;
tree[i].x=x;//该区间最新的x
tree[i].c+=flag;//更新覆盖
return ans;
}
return insert(i<<,x,l,r,flag)+insert(i<<|,x,l,r,flag);
}
int main(){
while(scanf("%d",&n),n){
k=;
for(int i=;i<=n;i++){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
y[++k]=y1,p[k]=(P){x1,y1,y2,};
y[++k]=y2,p[k]=(P){x2,y1,y2,-};
}
sort(y+,y+k+);
sort(p+,p+k+,cmp);
//没有去重,其实数量少,没必要。
build(,,k);
dd ans=;
for(int i=;i<=k;i++)
ans+=insert(,p[i].x,p[i].y1,p[i].y2,p[i].f);
printf("Test case #%d\nTotal explored area: %.2f\n\n",++num,ans);
}
return ;
}
【HDU 1542】Atlantis(线段树+离散化,矩形面积并)的更多相关文章
- POJ 1151 / HDU 1542 Atlantis 线段树求矩形面积并
题意:给出矩形两对角点坐标,求矩形面积并. 解法:线段树+离散化. 每加入一个矩形,将两个y值加入yy数组以待离散化,将左边界cover值置为1,右边界置为2,离散后建立的线段树其实是以y值建的树,线 ...
- POJ 1151 Atlantis 线段树求矩形面积并 方法详解
第一次做线段树扫描法的题,网搜各种讲解,发现大多数都讲得太过简洁,不是太容易理解.所以自己打算写一个详细的.看完必会o(∩_∩)o 顾名思义,扫描法就是用一根想象中的线扫过所有矩形,在写代码的过程中, ...
- HDU 1542.Atlantis-线段树求矩形面积并(离散化、扫描线/线段树)-贴模板
好久没写过博客了,这学期不是很有热情去写博客,写过的题也懒得写题解.现在来水一水博客,写一下若干年前的题目的题解. Atlantis Time Limit: 2000/1000 MS (Java/Ot ...
- HDU 1542 Atlantis(线段树面积并)
描述 There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. S ...
- HDU 1542 Atlantis (线段树 + 扫描线 + 离散化)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- HDU 1542 - Atlantis - [线段树+扫描线]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542 Time Limit: 2000/1000 MS (Java/Others) Memory Li ...
- HDU 1542 Atlantics 线段树+离散化扫描
将 x 轴上的点进行离散化,扫描线沿着 y 轴向上扫描 每次添加一条边不断找到当前状态有效边的长度 , 根据这个长度和下一条边形成的高度差得到一块合法的矩形的面积 #include<iostre ...
- hdu 1542 Atlantis(线段树,扫描线)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- hdu 1542 Atlantis (线段树扫描线)
大意: 求矩形面积并. 枚举$x$坐标, 线段树维护$[y_1,y_2]$内的边是否被覆盖, 线段树维护边时需要将每条边挂在左端点上. #include <iostream> #inclu ...
- HDU 1255 覆盖的面积 (扫描线 线段树 离散化 矩形面积并)
题目链接 题意:中文题意. 分析:纯手敲,与上一道题目很相似,但是刚开始我以为只是把cnt>=0改成cnt>=2就行了,. 但是后来发现当当前加入的线段的范围之前 还有线段的时候就不行了, ...
随机推荐
- poj2580 Super Memmo
Description Your friend, Jackson is invited to a TV show called SuperMemo in which the participant i ...
- ASP.NET Repeater 绑定 DropDownList Calendar 选择日期
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...
- f2fs中node page的lock_page
[都是思想片段, 待好好整理] node page的lock_page首先是为了改变page的状态:set_page_dirty, 还有set_nid操作时也会设置父节点的nid, 但是这样设置nod ...
- poj 3255 Roadblocks
Roadblocks Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 13216 Accepted: 4660 Descripti ...
- Easyui Tree方法扩展 - getLevel(获取节点级别)
Easyui Tree一直就没有提供这个方法,以前没有用到,所以一直没怎么在意,这次自己用到了,顺便扩展了一个方法,分享给大家. $.extend($.fn.tree.methods, { getLe ...
- Linux 网络编程详解六(多进程服务器僵尸进程解决方案)
小结:在点对点p2p程序中,服务器端子程序退出,子进程会主动发送信号,关闭父进程,但是这种模式导致服务器只能支持一个客户端连接,本章节中使用新的框架,子进程退出,不主动发送信号关闭父进程,而是父进程安 ...
- &12 二叉搜索树
#1,定义 二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的 ...
- 前端见微知著番外篇:Bitbucket进行代码管控
说道代码管控,一般都会提到TFS.Git等,但是在这里我们将要用到Bitbucket,其实其操作方式和Git基本上一样,但是和TFS则有很大的不同了.但是原理基本上都是一致的. 这里我不会过多的涉及到 ...
- 如何用 fiddler 捕获 https 请求
安装完 Fiddler 后,我们每次打开浏览器输入 url,Fiddler 便会捕获到我们的 http 请求(Fiddler 是以代理 web 服务器的形式工作的,它使用代理地址:127.0.0.1, ...
- 【位运算经典应用】 N皇后问题
说到位运算的经典应用,不得不说N皇后问题. 学过程序设计的都知道N皇后问题,没听过也没关系.很简单,最传统的的N皇后问题是这个样子的,给你一个n * n大小的board,让你放n个皇后(国际象棋),要 ...