链接:线段树求矩形面积并 扫描线+离散化

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 覆盖的面积(线段树求矩形面积交 扫描线+离散化)的更多相关文章

  1. POJ 1151 / HDU 1542 Atlantis 线段树求矩形面积并

    题意:给出矩形两对角点坐标,求矩形面积并. 解法:线段树+离散化. 每加入一个矩形,将两个y值加入yy数组以待离散化,将左边界cover值置为1,右边界置为2,离散后建立的线段树其实是以y值建的树,线 ...

  2. HDU 1828 / POJ 1177 Picture --线段树求矩形周长并

    题意:给n个矩形,求矩形周长并 解法:跟求矩形面积并差不多,不过线段树节点记录的为: len: 此区间线段长度 cover: 此区间是否被整个覆盖 lmark,rmark: 此区间左右端点是否被覆盖 ...

  3. 【hdu1542】线段树求矩形面积并

    分割线内容转载自http://hzwer.com/879.html ------------------------------------------------------------------ ...

  4. POJ 1151 Atlantis 线段树求矩形面积并 方法详解

    第一次做线段树扫描法的题,网搜各种讲解,发现大多数都讲得太过简洁,不是太容易理解.所以自己打算写一个详细的.看完必会o(∩_∩)o 顾名思义,扫描法就是用一根想象中的线扫过所有矩形,在写代码的过程中, ...

  5. 【hdu1255】线段树求矩形面积交

    题意大概就是上图这个样子.<=100组测试数据,每组<=1000个矩形. 题解: 这个问题怎么解决..做了上一题矩形面积并应该就会了.. 对于每个节点维护3个值: cnt:该节点所代表的这 ...

  6. POJ 1151Atlantis 扫描线+线段树求矩形面积并

    题目链接 #include <iostream> #include <vector> #include <cstdio> #include <cstring& ...

  7. UVA 11983 Weird Advertisement --线段树求矩形问题

    题意:给出n个矩形,求矩形中被覆盖K次以上的面积的和. 解法:整体与求矩形面积并差不多,不过在更新pushup改变len的时候,要有一层循环,来更新tree[rt].len[i],其中tree[rt] ...

  8. HDU 1542.Atlantis-线段树求矩形面积并(离散化、扫描线/线段树)-贴模板

    好久没写过博客了,这学期不是很有热情去写博客,写过的题也懒得写题解.现在来水一水博客,写一下若干年前的题目的题解. Atlantis Time Limit: 2000/1000 MS (Java/Ot ...

  9. HDU 3642 Get The Treasury ( 线段树 求长方体体积并 )

    求覆盖三次及其以上的长方体体积并. 这题跟 http://wenku.baidu.com/view/d6f309eb81c758f5f61f6722.html 这里讲的长方体体积并并不一样. 因为本题 ...

随机推荐

  1. [NOIP2002] 提高组P1032 字串变换

    题目描述 已知有两个字串 A, B 及一组字串变换的规则(至多6个规则): A1 -> B1 A2 -> B2 规则的含义为:在 A$中的子串 A1 可以变换为 B1.A2 可以变换为 B ...

  2. [NOIP1999] 提高组 洛谷P1014 Cantor表

    题目描述 现代数学的著名证明之一是Georg Cantor证明了有理数是可枚举的.他是用下面这一张表来证明这一命题的: 1/1 1/2 1/3 1/4 1/5 … 2/1 2/2 2/3 2/4 … ...

  3. 《TCP/IP详解卷1:协议》——第2章:链路层(转载)

    1.引言 从图1-4可以看出,在TCP/IP协议族中,链路层主要有三个目的: (1)为IP模块发送和接收IP数据报: (2)为ARP模块发送ARP请求和接收ARP应答. (3)为RARP发送RARP请 ...

  4. Android服务Service

    安卓Service服务 一    Service简介 Service是运行在后台的,没有界面的,用来处理耗时比较长的.Service不是一个单独的进程,也不是一个单独的线程. Service有两种类型 ...

  5. FLEX中restrict限定TextInput输入

    restrict限制的意思 1. 限制某个字符的输入,用符号 ^ 跟上要限制的字符,可跟多个字符  <!-- 限制字符"~"的输入 --> <mx:TextInp ...

  6. 推荐10+必备的 WordPress 常用插件

    众多的WordPress插件,使得WordPress的功能得到了较大的扩展,但是也正是由于过多的插件,导致我们很难选择所需的插件.今天,倡萌就根据自己的经验,给WordPress新手推荐一些常用的插件 ...

  7. python学习之- 生成器/迭代器

    列表生成式写法: [ i*2 for i in range(10) ]也可以带函数 [ fun(i) for i in range(10) ] 生成器:一边循环一边计算的机制称为生成器.在常用函数中, ...

  8. [Bzoj4540][Hnoi2016] 序列(莫队 + ST表 + 单调队列)

    4540: [Hnoi2016]序列 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1567  Solved: 718[Submit][Status] ...

  9. css三大布局

    标准流: 从左到右,从上到下块级元素独占一行,行内元素碰到父盒子边缘换行 浮动: 特点 1 元素浮动之后不占据原来的位置(脱标),变成立体,下面可以有东西,只影响下面的 2 浮动的盒子在一行上显示 3 ...

  10. ArcGIS Engine 中的多线程使用

    转自原文ArcGIS Engine 中的多线程使用 一直都想写写AE中多线程的使用,但一直苦于没有时间,终于在中秋假期闲了下来.呵呵,闲话不说了,进入正题! 大家都了解到ArcGIS中处理大数据量时速 ...