poj1151 Atlantis——扫描线+线段树
题目:http://poj.org/problem?id=1151
经典的扫描线问题;
可以用线段树的每个点代表横向被矩形上下边分割开的每一格,这样将一个矩形的出现或消失化为线段树上的单点修改;
每个格子记录两个值:c(矩形存在情况),sum(对当前答案作出贡献的长度);
将y离散化作为建树的依据;
一开始没想到线段树上的点应该是横向的格子,写了个乱七八糟:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int t,n,xt;
double s[],ans,tr[],mx,eps=0.36;
struct P{
double x,y1,y2;
int tp;
P(int x=,int y1=,int y2=,int t=):x(x),y1(y1),y2(y2),tp(t) {}
}p[];
void pushup(int x)
{
tr[x]=tr[x<<]+tr[x<<|];
}
void add(int x,double l,double r,double L,double R,int w)
{
// cout<<x<<endl;
// printf("l=%lf r=%lf eps=%lf\n",l,r,eps);
if(r-l<eps)
{
s[x]+=w;
if(s[x])tr[x]=;
else tr[x]=;
// printf("s[%d]=%d\n",x,s[x]);
return;
}
double mid=(l+r)/;
if(mid>=L)add(x<<,l,mid,L,R,w);
if(mid<R)add(x<<|,mid+,r,L,R,w);
pushup(x);
}
bool cmp(P x,P y){return x.x<y.x;}
int main()
{
while(scanf("%d",&n)==)
{
t++;xt=;mx=;ans=;
memset(tr,,sizeof tr);
memset(s,,sizeof s);
if(!n)return ;
for(int i=;i<=n;i++)
{
xt++;scanf("%lf%lf",&p[xt].x,&p[xt].y1);
xt++;scanf("%lf%lf",&p[xt].x,&p[xt].y1);
p[xt-].y2=p[xt].y1;p[xt].y2=p[xt-].y1;
p[xt-].tp=;p[xt].tp=-;
mx=max(mx,max(p[xt].y1,p[xt].y2));
}
sort(p+,p+xt+,cmp);
double lst=-;
for(int i=;i<=xt;i++)
{
if(p[i].y1>p[i].y2)swap(p[i].y1,p[i].y2);
add(,,mx,p[i].y1,p[i].y2,p[i].tp);
if(lst!=-)ans+=(p[i].x-lst)*tr[];
lst=p[i].x;
}
printf("Test case #%d\nTotal explored area: %.2lf \n",t,ans);
}
return ;
}
囧
然后参考别人的博客,努力理解了半天,模仿着打了出来,终于A了...
学到了add()函数里面那种二分的方法。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,ct,t;
double ans,y[];
struct P{
int l,r,c;//c为上下矩形抵消数
double ly,ry,sum;//sum为此时计入计算的长度
}tr[];
struct E{
int tp;
double x,ly,ry;
}ed[];
bool cmp(E x,E y){return x.x<y.x;}
void build(int x,int l,int r)
{
tr[x].l=l;tr[x].r=r;
tr[x].ly=y[l];tr[x].ry=y[r];
tr[x].c=;tr[x].sum=;
if(l==r-)return;
int mid=(l+r)>>;
build(x<<,l,mid);
build(x<<|,mid,r);//不是mid+1,因为l,r表示此块上下两边
}
void pushup(int x)
{
if(tr[x].c>)//全选
tr[x].sum=tr[x].ry-tr[x].ly;
else if(tr[x].l==tr[x].r-)//仅有一格且被退出
tr[x].sum=;
else//可能有其他边覆盖
tr[x].sum=tr[x<<].sum+tr[x<<|].sum;
}
void add(int x,E e)
{
if(tr[x].ly==e.ly&&tr[x].ry==e.ry)
{
tr[x].c+=e.tp;
pushup(x);
return;
}
if(tr[x<<].ry>=e.ry)add(x<<,e);
else if(tr[x<<|].ly<=e.ly)add(x<<|,e);
else
{
E tmp=e;
tmp.ry=tr[x<<].ry;
add(x<<,tmp);
tmp=e;
tmp.ly=tr[x<<|].ly;
add(x<<|,tmp);
}
pushup(x);
}
int main()
{
while(scanf("%d",&n)==)
{
t++;
if(!n)return ;
ct=;ans=;
for(int i=;i<=n;i++)
{
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
y[++ct]=y1;ed[ct].tp=;
ed[ct].x=x1;ed[ct].ly=y1;ed[ct].ry=y2;
y[++ct]=y2;ed[ct].tp=-;
ed[ct].x=x2;ed[ct].ly=y1;ed[ct].ry=y2;
}
sort(ed+,ed+ct+,cmp);
sort(y+,y+ct+);
build(,,ct);
add(,ed[]);
for(int i=;i<=ct;i++)
{
ans+=tr[].sum*(ed[i].x-ed[i-].x);
add(,ed[i]);//上下勿反
}
printf("Test case #%d\nTotal explored area: %.2f\n\n",t,ans);
}
return ;
}
poj1151 Atlantis——扫描线+线段树的更多相关文章
- poj1151 Atlantis (线段树+扫描线+离散化)
有点难,扫描线易懂,离散化然后线段树处理有点不太好理解. 因为这里是一个区间,所有在线段树中更新时,必须是一个长度大于1的区间才是有效的,比如[l,l]这是一根线段,而不是区间了. AC代码 #inc ...
- POJ 1151 Atlantis (扫描线+线段树)
题目链接:http://poj.org/problem?id=1151 题意是平面上给你n个矩形,让你求矩形的面积并. 首先学一下什么是扫描线:http://www.cnblogs.com/scau2 ...
- [HDU1542]Atlantis(扫描线+线段树)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Su ...
- 【POJ1151】Atlantis(线段树,扫描线)
[POJ1151]Atlantis(线段树,扫描线) 题面 Vjudge 题解 学一学扫描线 其实很简单啦 这道题目要求的就是若干矩形的面积和 把扫描线平行于某个轴扫过去(我选的平行\(y\)轴扫) ...
- hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积
题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> ...
- HDU 3642 - Get The Treasury - [加强版扫描线+线段树]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Others) Memory L ...
- 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树
[BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...
- HDU 3265/POJ 3832 Posters(扫描线+线段树)(2009 Asia Ningbo Regional)
Description Ted has a new house with a huge window. In this big summer, Ted decides to decorate the ...
- 【bzoj4491】我也不知道题目名字是什么 离线扫描线+线段树
题目描述 给定一个序列A[i],每次询问l,r,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串 输入 第一行n,表示A数组有多少元素接下来一行为n个整数A[i]接下来一个整数Q,表示询问数 ...
随机推荐
- Maven plugin提示错误“Plugin execution not covered by lifecycle configuration”
myeclipse在其POM文件的一处提示出错如下: Plugin execution not covered by lifecycle configuration: org.apache.maven ...
- Odoo10对套件的处理
Odoo10对套件的处理更强, 除了老版本支持的 销售套件, 按组件出货: 现在还增加了 采购套件, 按组件进货 建立 组件产品 KIT 设置 虚件BOM 测试, ...
- 【分布式计算】DFS && BigTable
1.背景 分布式计算的发迹应该是google在2003年发表的三篇paper.各自是GFS.MapReduce.BigTable. 当中MapReduce大家都非常熟悉了.不懂的同学也能够看看我之前写 ...
- vs 编译错误 The name 'InitializeComponent' does not exist in the current context in WPF application
1:文件命名空间的问题 xaml文件和model.cs文件的命名空间 2:csproj 那么它究竟是给谁用的呢?那是给开发工具用的,例如我们在熟悉不过的Visual Studio,以及大家可以没有接触 ...
- Spring Cloud(十):服务网关zuul(转)
前面的文章我们介绍了,Eureka用于服务的注册于发现,Feign支持服务的调用以及均衡负载,Hystrix处理服务的熔断防止故障扩散,Spring Cloud Config服务集群配置中心,似乎一个 ...
- UVA 10042 Smith Numbers(数论)
Smith Numbers Background While skimming his phone directory in 1982, Albert Wilansky, a mathematicia ...
- caffe搭建以及初步学习--win7-vs2013-gtx650tiboost-cuda8.0-cifar10训练和测试-2-快速解决方案cifar10_quick_solver.prototxt
首先安装好显卡----已经装好了?喜大普奔!没装好?那就用cpu,也是一样的. 拷贝cudnn v5.0 头文件和库文件以及执行文件到cuda8中 -------------------------- ...
- React Native组件解析(二)之Text
React Native组件解析(二)之Text 1. 概述 Text组件对应于iOS的UILabel,Android的TextView,用来显示文本.但是Text组件的内部使用的并不是flexbox ...
- Xcode 6 IDE
本文转载至 http://www.cocoachina.com/ios/20140823/9442.html (via:苹果开发者中心) Xcode IDE 是 Apple 开发体验的核心.X ...
- AAC包增加ADTS头Without MediaCodec
AAC原始码流无法直接播放,一般需要封装为ADTS格式才能再次使用,本博主在android中用MediaCodec编码得到的AAC就是raw格式,为了保存为.aac格式,需要增加adts头,这样就可以 ...