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

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. IDEA maven 无法加载已经安装的模块依赖包

    今天打包一直报如下错误 Reactor Summary for freechain-op 1.0.1.OP: [INFO] [INFO] freechain-op .................. ...

  2. xtu summer individual 2 D - Colliders

    Colliders Time Limit: 2000ms Memory Limit: 262144KB This problem will be judged on CodeForces. Origi ...

  3. 【HDOJ6335】Nothing is Impossible(贪心)

    题意: 有n道题目m个人,每道题目有1个正确选项和a[i]个错误选项,每个人每道题只能选一个选项 求出最坏情况下分数最多的人至少能拿到几分 n<=1e2,m<=1e9,1<=b[i] ...

  4. 10.1——pair,map,set,multimap,multiset

    map和set只允许相同的键出现一次,而multimap和multiset则允许出现多次. 1. 引言——pair类型: pair需要添加头文件utility头文件 make_pair<v1,v ...

  5. CodeIgniter框架的缓存原理分解

    用缓存的目的:(手册上叙述如下,已经写得很清楚了) Codeigniter 支持缓存技术,以达到最快的速度. 尽管CI已经相当高效了,但是网页中的动态内容.主机的内存CPU 和数据库读取速度等因素直接 ...

  6. Java并发包——线程安全的Collection相关类

    Java并发包——线程安全的Collection相关类 摘要:本文主要学习了Java并发包下线程安全的Collection相关的类. 部分内容来自以下博客: https://www.cnblogs.c ...

  7. 包装类Float中为什么有两个常量来表示最小值

    1)问:包装类Float中为什么有两个常量来表示最小值:MIN_VALUE和MIN_NORMAL ① MIN_VALUE:最小正非零值常量,是非规格化浮点数所能表示的最小值.值为 3.4E-45 的常 ...

  8. 【stl学习笔记】list

    list使用双向链表来管理元素. 与vector.deque的区别: 1.list不支持随机存取,在list中随机遍历任意元素,是很缓慢的行为 2.任何位置上执行元素的安插和移除都非常快,始终是常数时 ...

  9. CSS浮动通俗讲解

    首先要知道,div是块级元素,在页面中独占一行,自上而下排列,也就是传说中的流.如下图: 可以看出,即使div1的宽度很小,页面中一行可以容下div1和div2,div2也不会排在div1后边,因为d ...

  10. robotframework接口自动化

    robot framework框架在测试接口上比soapUI好用的多,在此介绍下get方法的HTTP接口,其实这个接口也是把POST数据作为参数进行get请求,使用post 方法也是一样,一共6步就可 ...