[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 ...
随机推荐
- C#中判断文件夹或文件是否存在的方法
一.根据虚拟路径获取文件物理路径: string savePath = Server.MapPath("~/Uploads/RemoteDatum/"); 二.判断文件夹是否存在 ...
- cookie以一个或多个空格开头
作为一个整体,如果cookie以一个或多个空格开头,请用空格替换所有空格:如果cookie以一个或多个空格结尾,请用空格替换所有空格. 象征意义: \ S:空间,空间 +一个或多个 ^开始,^s,以空 ...
- 99乘法表(js)
//九九乘法表 let i,j,str; for(i=1;i<=9;i++) { str = ""; for(j=1;j<=i;j++) { str = str+i+' ...
- git 多账户添加ssh秘钥
生成秘钥的步骤: ssh-keygen -t rsa -C "xxxx@qq.com" 添加秘钥 在不同的域中添加相同的秘钥是没有问题的,比如 github.com / code. ...
- tensorboardX使用中 AttributeError: 'function' object has no attribute 'graph'
最近在使用tensorboardX可视化网络结构,因为tensorboardX并非pytorch原生的可视化工具,所以版本之间并不兼容 在使用的过程中会遇到,AttributeError: 'func ...
- go语言入门(3)运算符及流程控制
1,运算符 算数运算符:+ - * / % ++ -- 关系运算符:== != < > <= >== 逻辑运算符:按位与 ...
- Java_Eclipse_Android安装
转自——链接:https://www.cnblogs.com/summary-2017/p/8073225.html
- Linq表达树(固定参数)
这篇博客只能用来批判因为我刚刚学习linq对它了解只有简单的linq to sql 的语句所以来写这个博客只能说是班门弄斧了,看的下去的话就坚持看吧. 在网上看了别人的文章目前水平有限借鉴别人的思想吧 ...
- uvalive 5905 Pool construction
题目链接 题意: 有一个花园,有些地方是草地,有些地方是洞,现在要在这个花园中修建一个泳池,泳池全部由洞构成. 把洞变成草地需要花费一定的费用,把草地变成洞也需要花费一定的费用,并且泳池的边缘的草地上 ...
- MyBatis Generator 移除字段前缀
在table标签内添加 <columnRenamingRule searchString="wrc_" replaceString=""/> < ...