hdu 1255 覆盖的面积(线段树 面积 交) (待整理)
Input
注意:本题的输入数据较多,推荐使用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 覆盖的面积(线段树 面积 交) (待整理)的更多相关文章
- HDU 1255 覆盖的面积(线段树面积并)
描述 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input 输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正 ...
- HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)
链接:线段树求矩形面积并 扫描线+离散化 1.给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 2.看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同. 求面积时,用被覆 ...
- 线段树扫描线(一、Atlantis HDU - 1542(覆盖面积) 二、覆盖的面积 HDU - 1255(重叠两次的面积))
扫描线求周长: hdu1828 Picture(线段树+扫描线+矩形周长) 参考链接:https://blog.csdn.net/konghhhhh/java/article/details/7823 ...
- hdu 1255 覆盖的面积(求覆盖至少两次以上的面积)
了校赛,还有什么途径可以申请加入ACM校队? 覆盖的面积 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K ...
- HDU 1542 Atlantis(线段树面积并)
描述 There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. S ...
- HDU 3016 Man Down (线段树+dp)
HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- HDU.5692 Snacks ( DFS序 线段树维护最大值 )
HDU.5692 Snacks ( DFS序 线段树维护最大值 ) 题意分析 给出一颗树,节点标号为0-n,每个节点有一定权值,并且规定0号为根节点.有两种操作:操作一为询问,给出一个节点x,求从0号 ...
- HDU.1556 Color the ball (线段树 区间更新 单点查询)
HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...
- HDU.1166 敌兵布阵 (线段树 单点更新 区间查询)
HDU.1166 敌兵布阵 (线段树 单点更新 区间查询) 题意分析 加深理解,重写一遍 代码总览 #include <bits/stdc++.h> #define nmax 100000 ...
随机推荐
- Android 如何全局获取Context
有时,在处理业务逻辑的时候,需要Context对象,但在某些情况下,并非容易获取,这时就需要一些巧妙的手段来管理Context. 在Android中,提供了一个类Application,当应用程序启动 ...
- windows 下svn 创建分支 合并分支 冲突
我用的系统是win7+Subversion 1.7.4.服务器搭建就略过了,我也是从网上找的,基本上就是几个命令吧!我用的CentOs6.5 .网上找了几个命令搭建很快,基本上是: 1.# sudo ...
- [tomcat] tomcat+nginx 负载均衡配置
首先下载,安装tomcat. 修改tomcat端口,修改server.xml: 1.修改tomcat端口(默认8080) <Connector port="8383" pro ...
- [mysql] mysql explain 使用
explain显示了mysql如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句. 先解析一条sql语句,看出现什么内容 EXPLAINSELECTs.uid, ...
- ubuntu 创建快捷方式
sudo ln -s /opt/eclipse/eclipse /usr/bin/eclipse 这样就可以在命令行中敲:eclipse,来打开eclipse了. 应该还有一种方式,就像快捷方式一样. ...
- 程序员书单_java web编程篇
李兴华JavaWeb开发实战经典 http://download.csdn.net/detail/shenzhq1980/9137653 Servlet与JSP核心编程 第2版_1 http://do ...
- java 反射机制01
// */ // ]]> java反射机制01 Table of Contents 1 反射机制 2 反射成员 2.1 java.lang.Class 2.2 Constructor 2.3 ...
- gcc杂谈
1. -l选项自动给库文件名增加lib前缀和.a/.so后缀.所以如果你有一个lib叫做libusb.a,那么编译选项是-lusb.另一方面,如果你有一个文件叫做libusb.o(是目标文件而不是库文 ...
- 理解和配置 Linux 下的 OOM Killer
原文:http://www.vpsee.com/2013/10/how-to-configure-the-linux-oom-killer/ 最近有位 VPS 客户抱怨 MySQL 无缘无故挂掉,还有 ...
- Linux命令之at
1.命令格式:at[参数][时间]2.命令功能:在一个指定的时间执行一个指定任务,只能执行一次,且需要开启atd进程(ps -ef | grep atd查看, 开启用/etc/init.d/atd s ...