HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)
链接:线段树求矩形面积并 扫描线+离散化
1、给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
2、看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同。
求面积时,用被覆盖2次以上的那一段乘以扫描线的距离即可,具体实现见代码。
3、
/*
HDU 1255 覆盖的面积
求矩形面积交(离散化+线段树)
给定一些矩形
求被这些矩形覆盖过至少两次的区域的面积 这里的方法是:线段树求矩形面积交 扫描线+离散化
左右扫描(x轴扫描),把y轴上的线段离散化
*/
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std; const int MAXN=; struct Node
{
int l,r;//离散化后的y值
double lf,rf;//原来的y值,lf代表l原来的y值,rf代表r原来的y值
int cnt;//当前段被覆盖过几次
double lenOnce;//当前段中覆盖一次以上的长度
double lenTwice;//当前段中覆盖两次以上的长度
} segTree[MAXN*];
struct Line
{
double x;//也就是对应的扫描线x坐标
double y1,y2;//线段的端点坐标
double f;//1表示一个矩形左边的边,-1表示右边的边
} line[MAXN]; double y[MAXN]; bool cmp(Line a,Line b)
{
return a.x<b.x;
} void Build(int i,int l,int r)
{
segTree[i].l=l;
segTree[i].r=r;
segTree[i].lenOnce=;
segTree[i].lenTwice=;
segTree[i].lf=y[l];
segTree[i].rf=y[r];
if(l+==r)return;
int mid=(l+r)>>;
Build(i<<,l,mid);
Build((i<<)|,mid,r);
}
void calen(int i)
{
if(segTree[i].cnt>=)//被线段覆盖次数>=2
{
segTree[i].lenOnce=segTree[i].rf-segTree[i].lf;
segTree[i].lenTwice=segTree[i].rf-segTree[i].lf;
return;
}
else if(segTree[i].cnt==)//被线段覆盖次数==1
{
segTree[i].lenOnce=segTree[i].rf-segTree[i].lf; if(segTree[i].l+==segTree[i].r)segTree[i].lenTwice=;//当是叶子节点时
else segTree[i].lenTwice=segTree[i<<].lenOnce+segTree[(i<<)|].lenOnce;
//因为当前线段被覆盖过1次,所以覆盖2次以上的长度是其左右孩子的覆盖1次以上的长度的和
}
else//被线段覆盖次数==0
{
if(segTree[i].l+==segTree[i].r)//当是叶子节点时
{
segTree[i].lenOnce=segTree[i].lenTwice=;
}
else
{//因为当前节点被覆盖次数为0,所以lenOnce和lenTwice的值由左右孩子决定
segTree[i].lenOnce=segTree[i<<].lenOnce+segTree[(i<<)|].lenOnce;
segTree[i].lenTwice=segTree[i<<].lenTwice+segTree[(i<<)|].lenTwice;
}
}
}
void update(int i,Line e)
{
if(e.y1==segTree[i].lf&&segTree[i].rf==e.y2)
{
segTree[i].cnt+=e.f;
calen(i);//更新当前节点信息
return;
} if(e.y2<=segTree[i<<].rf) update(i<<,e);
else if(e.y1>=segTree[(i<<)|].lf) update((i<<)|,e);
else
{
Line temp=e;
temp.y2=segTree[i<<].rf;
update(i<<,temp);
temp=e;
temp.y1=segTree[(i<<)|].lf;
update((i<<)|,temp);
}
calen(i);//更新当前节点信息
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
int n;
double x1,y1,x2,y2;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int t=;
for(int i=; i<=n; i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); //这里题目描述有问题?左下角和右上角
line[t].y1=y1;
line[t].y2=y2;
line[t].x=x1;
line[t].f=;//左边的边
y[t]=y1;//y坐标离散化(下端点)
t++; line[t].y1=y1;
line[t].y2=y2;
line[t].x=x2;
line[t].f=-;//右边的边
y[t]=y2;//y坐标离散化(上端点)
t++;
}
sort(line+,line+t,cmp);//线段按x的值升序排序
sort(y+,y+t);//y坐标从小下到大排序
Build(,,t-);//用离散化后的y值(也就是t)建立线段树 update(,line[]);//从第一条扫描线向右扫描
double ans=;
for(int i=; i<t; i++)
{
ans+=segTree[].lenTwice*(line[i].x-line[i-].x);
update(,line[i]);
}
printf("%.2lf\n",ans);
}
return ;
}
HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)的更多相关文章
- POJ 1151 / HDU 1542 Atlantis 线段树求矩形面积并
题意:给出矩形两对角点坐标,求矩形面积并. 解法:线段树+离散化. 每加入一个矩形,将两个y值加入yy数组以待离散化,将左边界cover值置为1,右边界置为2,离散后建立的线段树其实是以y值建的树,线 ...
- HDU 1828 / POJ 1177 Picture --线段树求矩形周长并
题意:给n个矩形,求矩形周长并 解法:跟求矩形面积并差不多,不过线段树节点记录的为: len: 此区间线段长度 cover: 此区间是否被整个覆盖 lmark,rmark: 此区间左右端点是否被覆盖 ...
- 【hdu1542】线段树求矩形面积并
分割线内容转载自http://hzwer.com/879.html ------------------------------------------------------------------ ...
- POJ 1151 Atlantis 线段树求矩形面积并 方法详解
第一次做线段树扫描法的题,网搜各种讲解,发现大多数都讲得太过简洁,不是太容易理解.所以自己打算写一个详细的.看完必会o(∩_∩)o 顾名思义,扫描法就是用一根想象中的线扫过所有矩形,在写代码的过程中, ...
- 【hdu1255】线段树求矩形面积交
题意大概就是上图这个样子.<=100组测试数据,每组<=1000个矩形. 题解: 这个问题怎么解决..做了上一题矩形面积并应该就会了.. 对于每个节点维护3个值: cnt:该节点所代表的这 ...
- POJ 1151Atlantis 扫描线+线段树求矩形面积并
题目链接 #include <iostream> #include <vector> #include <cstdio> #include <cstring& ...
- UVA 11983 Weird Advertisement --线段树求矩形问题
题意:给出n个矩形,求矩形中被覆盖K次以上的面积的和. 解法:整体与求矩形面积并差不多,不过在更新pushup改变len的时候,要有一层循环,来更新tree[rt].len[i],其中tree[rt] ...
- HDU 1542.Atlantis-线段树求矩形面积并(离散化、扫描线/线段树)-贴模板
好久没写过博客了,这学期不是很有热情去写博客,写过的题也懒得写题解.现在来水一水博客,写一下若干年前的题目的题解. Atlantis Time Limit: 2000/1000 MS (Java/Ot ...
- HDU 3642 Get The Treasury ( 线段树 求长方体体积并 )
求覆盖三次及其以上的长方体体积并. 这题跟 http://wenku.baidu.com/view/d6f309eb81c758f5f61f6722.html 这里讲的长方体体积并并不一样. 因为本题 ...
随机推荐
- Google JavaScript代码风格指南
Google JavaScript代码风格指南 修正版本 2.28 Aaron Whyte Bob Jervis Dan Pupius Eric Arvidsson Fritz Schneider R ...
- Struts2的Action配置的各项默认值
1 如果没有为action指定class,默认是ActionSupport 2 如果没有为action指定method,默认执行action中的execute()方法 3 如果没有指定result的n ...
- Computers(线性DP)
描述 Everybody is fond of computers, but buying a new one is always a money challenge. Fortunately, th ...
- Android GradientDrawable的XML实现
Android GradientDrawable的XML实现 Android GradientDrawable与附录文章1类似,这次以XML而非Java代码形式实现.比如写好一个shape文件放 ...
- 在RedHat 5下安装Oracle 10g详解(转)
在RedHat 5下安装Oracle 10g详解(转) Posted on 2012-09-14 13:26 疯狂 阅读(5075) 评论(0) 编辑 收藏 所属分类: database .uni ...
- 2016 Multi-University Training Contest 9 solutions BY 金策工业综合大学
A Poor King Tag: Reversed BFS Preprocessing is needed to calculate answers for all positions (states ...
- PB编译
java -jar wire-compiler-1.8.0-jar-with-dependencies.jar --java_out=./ ngame.proto 其中java_out是指输出要放在 ...
- TimePickerDialog
package com.pingyijinren.helloworld.activity; import android.app.TimePickerDialog; import android.su ...
- js删除数组对象中符合条件的数据
var data = [{}, {}, {}, {Id:1}] var datawilldele = [];//2,4,5 data.forEach(function (v, i,arry) { if ...
- EclipseEE的Web开发环境配置(使用Tomcat作为Web服务器)
进行JavaWeb开发,我们总共需要5个步骤:JDK的安装与配置:Tomcat的安装:EclipseEE的安装与配置:创建工程;编写代码并运行.安装的三个软件在版本和适用构架上要一致.当JDK是32位 ...