题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255

Description

给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.





 

Input

输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N&lt;=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.



注意:本题的输入数据较多,推荐使用scanf读入数据.
 

Output

对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
 

Sample Input

2
5
1 1 4 2
1 3 3 7
2 1.5 5 4.5
3.5 1.25 7.5 4
6 3 10 7
3
0 0 1 1
1 0 2 1
2 0 3 1
 

Sample Output

7.63
0.00
 



点更新:
#include <iostream>
#include <algorithm>
#include <stdio.h>
using namespace std;
const int maxn=1100;
struct LINE
{
double x, y_down, y_up;
int flag;
bool operator<(const LINE &a)const ///按照x从小到大的顺序排序
{
return x<a.x;
}
}line[2*maxn]; struct TREE
{
double x,y_down, y_up;
int cover; ///用以表示加进线段树中的线段次数
bool flag; ///标记叶子节点
}tree[maxn*8]; double y[2*maxn]; void build(int i, int l, int r) ///当前节点下标,l , r 线段树建立左右线数组下标
{
tree[i].x = -1; //-1表示该区间已经没有线段
tree[i].cover = 0; //表示该区间上有多少条线段;左边线段加进去则++,右边线段加进去则--
tree[i].y_down = y[l];
tree[i].y_up = y[r];
tree[i].flag = false;
if(l+1==r)
{
tree[i].flag = true; //flag==true表示达到了叶子节点
return;
}
int mid=(l+r)>>1;
build(2*i, l, mid);
build(2*i+1, mid, r);
} double insert(int i, double x, double l, double r, int flag) //flag表示为左边还是右边
{
if ( r<=tree[i].y_down || l>=tree[i].y_up ) return 0;
if (tree[i].flag) /// 叶子节点
{
if (tree[i].cover > 1) /// 该区域的面积存在,且未经计算
{
double temp_x = tree[i].x;
double ans=( x-temp_x )*(tree[i].y_up - tree[i].y_down);
tree[i].cover += flag;
tree[i].x = x; //定位上一次的x
return ans;
}
else ///虽然是叶子节点,但是需要更新当前的线段覆盖标记
{
tree[i].cover += flag;
tree[i].x = x; ///更新最新x
return 0;
}
}
return insert(2*i, x, l, r, flag)+insert(2*i+1, x, l, r, flag); ///不是叶子节点就往下递归
} int main( )
{
// freopen("d:\\in.txt","r",stdin);
int n,index;
double x1, y1, x2, y2;
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n) ;
index = 1;
for (int i=1; i<=n; i++)
{
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
y[index] = y1;
line[index].x = x1;
line[index].y_down = y1;
line[index].y_up = y2;
line[index++].flag = 1; //1表示左边 y[index] = y2;
line[index].x = x2;
line[index].y_down = y1;
line[index].y_up = y2;
line[index++].flag = -1; //-1表示右边
}
sort(&y[1], &y[index]); //把所有的纵坐标按从小到大排序,把1写成了0,WA一次
sort(&line[1], &line[index]);
build(1, 1, index-1);
double ans=0;
for (int i=1;i<index; i++) ///将线line从左向右遍历
ans+=insert(1, line[i].x, line[i].y_down, line[i].y_up, line[i].flag);
printf("%.2f\n", ans);
}
return 0;
}

区间更新:

/*
HDU 1255 覆盖的面积
求矩形交的面积(线段树+离散化)
给定一些矩形
被这些矩形覆盖过至少两次的区域的面积
*/
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 2010
struct Node
{
int l,r; ///线段树的左右整点
int c; ///c用来记录重叠情况
double lf,rf; ///rf,lf分别是对应的左右真实的浮点数端点
double cnt,more;///cnt是值被覆盖一次以上的长度,more值被覆盖两次以上的长度
}segTree[MAXN*3];
struct Line
{
double x,y_down,y_up;
int flag;
}line[MAXN];
///用来记录重叠情况,可以根据这个来计算,nod节点中的c bool cmp(Line a,Line b)//sort排序的函数
{
return a.x < b.x;
} double y[MAXN];//记录y坐标的数组
void Build(int t,int l,int r)//构造线段树
{
segTree[t].l=l;
segTree[t].r=r;
segTree[t].cnt=segTree[t].c=0;
segTree[t].lf=y[l];
segTree[t].rf=y[r];
if(l+1==r)
return;
int mid=(l+r)>>1;
Build(t<<1,l,mid);
Build(t<<1|1,mid,r);//递归构造
}
void calen(int t)//计算长度
{
if(segTree[t].c>=2) ///该区间被覆盖两次或以上
{
segTree[t].more=segTree[t].cnt=segTree[t].rf-segTree[t].lf;
return;
}
else if(segTree[t].c==1) ///该区间被覆盖一次
{
segTree[t].cnt = segTree[t].rf-segTree[t].lf;
if(segTree[t].l+1==segTree[t].r)
segTree[t].more=0;
else
segTree[t].more = segTree[t<<1].cnt + segTree[t<<1|1].cnt;
}
else ///该区间
{
if(segTree[t].l+1==segTree[t].r) ///子节点
segTree[t].more=segTree[t].cnt=0;
else ///非子节点
{
segTree[t].cnt=segTree[t<<1].cnt+segTree[ t<<1|1 ].cnt;
segTree[t].more=segTree[t<<1].more+segTree[ t<<1|1 ].more;
}
}
}
void update(int t,Line line)//加入线段e,后更新线段树
{
if( line.y_down==segTree[t].lf && line.y_up==segTree[t].rf ) ///恰好是当前的区间
segTree[t].c += line.flag;
else{
if(line.y_up<=segTree[t<<1].rf) ///需要更新的区间在当前节点的左孩子节点中
update(t<<1,line);
else if(line.y_down>=segTree[t<<1|1].lf) ///需要更新的区间在当前节点的右孩子节点中
update(t<<1|1,line);
else ///横跨左右两个孩子节点
{
Line tmp=line;
tmp.y_up=segTree[t<<1].rf;
update(t<<1,tmp);
tmp=line;
tmp.y_down=segTree[t<<1].rf;
update(t<<1|1,tmp);
}
}
calen(t);
}
int main()
{
int i,n,t,T;
double x1,y1,x2,y2;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
t=1;
for(i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[t].x=x1;
line[t].y_down=y1;
line[t].y_up=y2;
line[t].flag=1;
y[t++]=y1; line[t].x=x2;
line[t].y_down=y1;
line[t].y_up=y2;
line[t].flag=-1;
y[t++]=y2;
}
sort(line+1,line+t,cmp);
sort(y+1,y+t);
Build(1,1,t-1);
double res=0;
for(i=1;i<t;i++)
{
update(1,line[i]);
res += segTree[1].more*(line[i+1].x-line[i].x);
}
printf("%.2lf\n",res);
}
return 0;
}

hdu 1255 覆盖的面积(线段树 面积 交) (待整理)的更多相关文章

  1. HDU 1255 覆盖的面积(线段树面积并)

      描述 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input 输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正 ...

  2. HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)

    链接:线段树求矩形面积并 扫描线+离散化 1.给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 2.看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同. 求面积时,用被覆 ...

  3. 线段树扫描线(一、Atlantis HDU - 1542(覆盖面积) 二、覆盖的面积 HDU - 1255(重叠两次的面积))

    扫描线求周长: hdu1828 Picture(线段树+扫描线+矩形周长) 参考链接:https://blog.csdn.net/konghhhhh/java/article/details/7823 ...

  4. hdu 1255 覆盖的面积(求覆盖至少两次以上的面积)

    了校赛,还有什么途径可以申请加入ACM校队?  覆盖的面积 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K ...

  5. HDU 1542 Atlantis(线段树面积并)

     描述 There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. S ...

  6. HDU 3016 Man Down (线段树+dp)

    HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  7. HDU.5692 Snacks ( DFS序 线段树维护最大值 )

    HDU.5692 Snacks ( DFS序 线段树维护最大值 ) 题意分析 给出一颗树,节点标号为0-n,每个节点有一定权值,并且规定0号为根节点.有两种操作:操作一为询问,给出一个节点x,求从0号 ...

  8. HDU.1556 Color the ball (线段树 区间更新 单点查询)

    HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...

  9. HDU.1166 敌兵布阵 (线段树 单点更新 区间查询)

    HDU.1166 敌兵布阵 (线段树 单点更新 区间查询) 题意分析 加深理解,重写一遍 代码总览 #include <bits/stdc++.h> #define nmax 100000 ...

随机推荐

  1. python函数: 内置函数

    forthttp://blog.csdn.net/pipisorry/article/details/44755423 Python内置函数 Python内置(built-in)函数随着python解 ...

  2. SQL Server 日期的加减函数: DATEDIFF DATEADD

    SQL Server 日期的加减函数: DATEDIFF    DATEADD DATEDIFF: 返回跨两个指定日期的日期边界数和时间边界数, 语法:DATEDIFF ( datepart , st ...

  3. mysql row number的实现

    CREATE TABLE `test_id` (`id` int(11) NOT NULL DEFAULT 0 ,`name` varchar(255) CHARACTER SET utf8 COLL ...

  4. exp命令ORACLCE10G导出ORACLE11G的数据1455错误

    异常:1455 解决: 命令:exp youruser/password@192.xxx.x.xx:1521/orcl owner=youruser file=c:\export.dmp trigge ...

  5. Angular学习(8)- 路由

    示例: <!DOCTYPE html> <html ng-app="MyApp"> <head> <title>Study 12&l ...

  6. [转]UOS 中的虚拟网络设备

    随着网络技术,虚拟化技术的发展,越来越多的高级网络设备被加入了到了 Linux 中,这些设备在 UOS 中起到了广泛而关键的作用,包括 Open vSwitch.TAP 设备.Veth 设备等等,梳理 ...

  7. LintCode "Count of Smaller Number before itself"

    Warning: input could be > 10000... Solution by segment tree: struct Node { Node(), left(nullptr), ...

  8. bzoj2467: [中山市选2010]生成树

    Description 有一种图形叫做五角形圈.一个五角形圈的中心有1个由n个顶点和n条边组成的圈.在中心的这个n边圈的每一条边同时也是某一个五角形的一条边,一共有n个不同的五角形.这些五角形只在五角 ...

  9. 可以返回执行结果的system函数加强版本

    在GNU Linux C编程中,要想进行系统命令的执行的话,只提供了system接口,但是此接口并不能得到命令执行后所输出的值,而只能够得到命令是否执行成功的结果.仅仅这样的功能还是不够的,有的时候是 ...

  10. activiti自定义流程之Spring整合activiti-modeler5.16实例(五):流程定义列表

    注:(1)环境搭建:activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建        (2)创建流程模型:activiti自定义流程之Spring ...