[POJ1151][HDU1542]Atlantis(线段树,扫描线)
英文题面,我就只放个传送门了。
Solution
题意是算矩形面积并,这是扫描线算法能解决的经典问题。
算法的大致思想是,把每一个矩形拆成上边和下边(以下称作扫描线),每条扫描线有四个参数l,r,h,v。l和r为它的左右端点的横坐标,h为扫描线的纵坐标,v下面再解释。
然后把扫描线按h从小到大排序,想一想,所有相邻扫描线之间的有效面积(即被矩形覆盖的面积)加起来是不是就是ans?
怎么求呢?我们从下往上处理,设当前处理到第i条扫描线,设第i条扫描线与第i+1条扫描线之间的有效面积为s,那么s=(h[i+1]-h[i])*此时x轴被覆盖的长度。
考虑用线段树来维护这个“x轴被覆盖的长度“,处理到第i条扫描线时,就把区间[l[i],r[i]]覆盖一次。但是这个覆盖是有时限的,当扫到某一条上边时,它对应的下边所产生的覆盖就应该被消去。
为了方便地处理,我们把下边的v值设为1,上边的v值设为-1,这样修改时直接把区间[l[i],r[i]]的覆盖次数加v就好了。
具体实现时,x坐标要离散化,线段树中用cnt来表示区间被覆盖的次数,sum来表示区间(当然都是在x轴上)内的覆盖长度。
注意两点:
- 线段树上一个叶子节点i实际上表示的是x轴上[i,i+1]这一段,因此线段树只需要n-1个叶子节点。
- 由于我们只需要查询sum[1],所以update找到需修改的区间可以直接pushup,并且不用pushdown。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
struct line{
double l,r,h;int v;
line(){}
line(double a,double b,double c,int d):l(a),r(b),h(c),v(d){}
bool operator < (const line &tmp)const{return h<tmp.h;}
}L[N];
int cnt[N<<];
double X[N],sum[N<<];
#define tl id<<1
#define tr id<<1|1
#define mid ((l+r)>>1)
#define lson tl,l,mid
#define rson tr,mid+1,r
void pushup(int id,int l,int r){
if(cnt[id]) sum[id]=X[r+]-X[l];
else if(l==r) sum[id]=;
else sum[id]=sum[tl]+sum[tr];
}
void update(int id,int l,int r,int ll,int rr,int v){
if(ll<=l&&r<=rr){
cnt[id]+=v;
pushup(id,l,r);
return ;
}
if(ll>mid) update(rson,ll,rr,v);
else if(rr<=mid) update(lson,ll,rr,v);
else update(lson,ll,rr,v),update(rson,ll,rr,v);
pushup(id,l,r);
}
int n,m,cas;
int main(){
while(~scanf("%d",&n)&&n){
m=;memset(cnt,,sizeof cnt);memset(sum,,sizeof sum);
for(int i=;i<n;++i){
double a,b,c,d;
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
L[m]=line(a,c,b,);
X[m++]=a;
L[m]=line(a,c,d,-);
X[m++]=c;
}
sort(&L[],&L[m]);
sort(&X[],&X[m]);n=unique(&X[],&X[m])-X;
double s=;
for(int i=;i<m;++i){
int l=lower_bound(&X[],&X[n],L[i].l)-X,r=lower_bound(&X[],&X[n],L[i].r)-X-;
update(,,n-,l,r,L[i].v);
s+=sum[]*(L[i+].h-L[i].h);
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",++cas,s);
//POJ上提交G++的同学请改为%.2f
}
return ;
}
扫描线
[POJ1151][HDU1542]Atlantis(线段树,扫描线)的更多相关文章
- hdu1542 Atlantis 线段树--扫描线求面积并
There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some ...
- HDU 1542 - Atlantis - [线段树+扫描线]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542 Time Limit: 2000/1000 MS (Java/Others) Memory Li ...
- POJ1151 Atlantis 线段树扫描线
扫描线终于看懂了...咕咕了快三个月$qwq$ 对于所有的横线按纵坐标排序,矩阵靠下的线权值设为$1$,靠上的线权值设为$-1$,然后执行线段树区间加减,每次的贡献就是有效宽度乘上两次计算时的纵坐标之 ...
- HDU 1542 Atlantis (线段树 + 扫描线 + 离散化)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- 【42.49%】【hdu 1542】Atlantis(线段树扫描线简析)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s) ...
- POJ 1151 - Atlantis 线段树+扫描线..
离散化: 将所有的x轴坐标存在一个数组里..排序.当进入一条线段时..通过二分的方式确定其左右点对应的离散值... 扫描线..可以看成一根平行于x轴的直线..至y=0开始往上扫..直到扫出最后一条平行 ...
- POJ 1151:Atlantis 线段树+扫描线
Atlantis Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 19374 Accepted: 7358 Descrip ...
- hdu 1542 Atlantis (线段树扫描线)
大意: 求矩形面积并. 枚举$x$坐标, 线段树维护$[y_1,y_2]$内的边是否被覆盖, 线段树维护边时需要将每条边挂在左端点上. #include <iostream> #inclu ...
- hdu1542 Atlantis (线段树+矩阵面积并+离散化)
There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some ...
- hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
随机推荐
- exclipe怎么设置编码为UTF-8
如果要使插件开发应用能有更好的国际化支持,能够最大程度的支持中文输出,则最好使 Java文件使用UTF-8编码.然而,Eclipse工作空间(workspace)的缺省字符编码是操作系统缺省的编码,简 ...
- Autofac通过配置的方式
autofac是比较简单易用的IOC容器.下面我们展示如何通过json配置文件,来进行控制反转. 需要用到以下程序集.可以通过nugget分别安装 Microsoft.Extensions.Confi ...
- Bootstrap3基础教程 03 导航栏
Bootstrap导航栏 创建一个默认的导航栏的步骤如下: 1.向 <nav> 标签添加 class .navbar..navbar-default. 2.向上面的元素添加 role=&q ...
- git的详细安装
git的详细安装 Git 是时候动手尝试下 Git 了,不过得先安装好它.有许多种安装方式,主要分为两种,一种是通过编译源代码来安装:另一种是使用为特定平台预编译好的安装包. 从源代码安装 若是条件允 ...
- vue 项目中如何在页面刷新的状态下保留数据
1.问题:在vue项目中,刷新页面之后,我当前打开的所有菜单,都消失,我如何实现刷新之后页面仍然是刷新之前的状态 效果图: 解决方法: 使用vuex作状态管理: 将vuex里面的数据同步更新到loca ...
- Redis-Hash常用命令
Redis-Hash常用命令 hset key field value 设置一个散列,但是在散列中一次只能设置一个属性,如果要批量设置多个属性,则需要使用 hmset命令 hget key field ...
- SQL Server 分页SQL
SELECT * FROM(SELECT ROW_NUMBER() OVER(order by Id DESC)AS rownum, (SELECT COUNT(*) FROM Ana_Strateg ...
- Codeforce Round #424
A 略 B 略 C: 先对Ai数列预处理前缀和 然后把Bi的每个都加一次 最终得到的结果为ans[sum]++; 最后如果有一个ans[sum]>=k即满足所有K个条件就输出(注意!!前缀和要进 ...
- winform Combox绑定数据时不触发SelectIndexChanged事件
做了一个仓库选择的联动,选了仓库选其下的货区,选了货区选其下的货架分区.每个combox初始化.绑定数据是都会触发SelectIndexChanged事件,相当头疼. 后来无意中在网上看到了一种方法— ...
- linux 发送 post 请求
curl -H "Content-type: application/json" -X POST -d '{"accoId":"IDAP_000000 ...