HDU - 1255 扫描线+离散化进阶
这道题最开始我以为和HDU - 1542 那道题一样,只需要把cover次数改成2次即可,但是后面仔细一想,我们需要求的是覆盖次数大于等于2次的,这样的话,我们需要维护两个长度,HDU-1542 由于求的是覆盖次数大于等于一次的,我们只需要维护一个覆盖次数大于等于1的长度的len1就行,但是这道题我们要求的是覆盖两次以及两次以上的长度,这样乘以高度差,才是面积。
现在我们来想如何维护这个值?
给线段树打个标记cover,代表这个区间被完全覆盖的次数。
我们先来看看,维护覆盖一次及其以上的,应该怎么实现,我们可以从中得到启示。
- cover不为0 那么这个区间被完全覆盖。我们把整个区间长度给len1,但是我们由于经过离散化。表达式为:tree[root].len1=pos[r+1]-pos[l]
- L==R 代表跑到了叶子节点,不会有节点信息往上传,因此赋0
- 不满足上述两者,我们就可以认为,父节点的信息,又两个儿子节点的提供。
那么覆盖两次的呢?同样的分情况讨论
- cover>1 那么这个区间内被完全覆盖至少2次,值等于区间长度。
- L==R 同样的信息不能由子节点提供,赋0。
- Cover==1 那么这个区间被完全覆盖至少一,子节点覆盖次数大于等于1的次数往上pushup后,变成至少两次。
- 反之节点信息由两个子节点提供
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
inline int L(int r)
{
return r<<;
};
inline int R(int r)
{
return r<<|;
};
inline int MID(int l,int r)
{
return (l+r)>>;
};
const int maxx = ;
struct Line
{
double l,r,h;
int f;
}line[maxx*];
struct node
{
int l,r,cover;
double len1,len2;
} tree[maxx<<];
double pos[maxx];
bool cmp(Line a,Line b){
return a.h<b.h;
}
void buildtree(int root,int l,int r)//建树
{
tree[root].l=l;
tree[root].r=r;
tree[root].len1=;
tree[root].len2=;
tree[root].cover=;
if (l==r)
{
return;
}
int mid = MID(l,r);
buildtree(L(root),l,mid);
buildtree(R(root),mid+,r);
}
int bin(double key,int low,int high)
{
while(low<=high)
{
int mid = (low+high)>>;
if (pos[mid] == key)
return mid;
else if (pos[mid] < key)
low = mid+;
else
high = mid-;
}
return -;
}
void pushup(int root)
{
int l=tree[root].l;
int r=tree[root].r;
if (tree[root].cover)tree[root].len1=pos[r+]-pos[l];
else if (l==r)tree[root].len1=;
else tree[root].len1=tree[L(root)].len1+tree[R(root)].len1; if (tree[root].cover>)tree[root].len2=tree[root].len1;
else if (l==r)tree[root].len2=;
else if (tree[root].cover==)tree[root].len2=tree[L(root)].len1+tree[R(root)].len1;
else tree[root].len2=tree[L(root)].len2+tree[R(root)].len2;
}
void update(int root,int ul,int ur,int c)
{
int l=tree[root].l;
int r=tree[root].r;
if (ul<=l && r<=ur)
{
tree[root].cover+=c;
pushup(root);
return;
}
int mid=MID(l,r);
if (ur<=mid)update(L(root),ul,ur,c);
else if (ul>mid)update(R(root),ul,ur,c);
else {
update(L(root),ul,mid,c);
update(R(root),mid+,ur,c);
}
pushup(root);
}
int main()
{
int t;
scanf("%d",&t);
int n;
while(t--){
int nums=;
scanf("%d",&n);
for (int i=;i<n;i++){
double x1,x2,y1,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[nums].l=x1;
line[nums].r=x2;
line[nums].h=y1;
line[nums].f=;
pos[nums++]=x1;
line[nums].l=x1;
line[nums].r=x2;
line[nums].h=y2;
line[nums].f=-;
pos[nums++]=x2;
}
sort(pos,pos+nums);
sort(line,line+nums,cmp);
int m=;
for (int i=;i<nums;i++)//去重
if (pos[i]!=pos[i-])
pos[m++]=pos[i];
buildtree(,,m-);
double ans=;
for (int i=;i<nums;i++)
{
int l=bin(line[i].l,,m-);
int r=bin(line[i].r,,m-)-;
update(,l,r,line[i].f);
ans+=tree[].len2*(line[i+].h-line[i].h);
}
printf("%.2lf\n",ans);
}
return ;
}
HDU - 1255 扫描线+离散化进阶的更多相关文章
- HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)
链接:线段树求矩形面积并 扫描线+离散化 1.给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 2.看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同. 求面积时,用被覆 ...
- 线段树扫描线(一、Atlantis HDU - 1542(覆盖面积) 二、覆盖的面积 HDU - 1255(重叠两次的面积))
扫描线求周长: hdu1828 Picture(线段树+扫描线+矩形周长) 参考链接:https://blog.csdn.net/konghhhhh/java/article/details/7823 ...
- 扫描线三巨头 hdu1928&&hdu 1255 && hdu 1542 [POJ 1151]
学习链接:http://blog.csdn.net/lwt36/article/details/48908031 学习扫描线主要学习的是一种扫描的思想,后期可以求解很多问题. 扫描线求矩形周长并 hd ...
- HDU 1255 覆盖的面积(线段树+扫描线)
题目地址:HDU 1255 这题跟面积并的方法非常像,仅仅只是须要再加一个变量. 刚開始我以为直接用那个变量即可,仅仅只是推断是否大于0改成推断是否大于1.可是后来发现了个问题,由于这个没有下放,没延 ...
- hdu 1255 覆盖的面积(线段树 面积 交) (待整理)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 Description 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. In ...
- hdu1542 Atlantis (线段树+扫描线+离散化)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- hdu 1255 覆盖的面积(求覆盖至少两次以上的面积)
了校赛,还有什么途径可以申请加入ACM校队? 覆盖的面积 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K ...
- HDU 1255 覆盖的面积 (线段树+扫描线+离散化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 题意很清楚,就是让你求矩阵之间叠加层数大于1的矩形块的面积和. 因为n只有1000,所以我离散化 ...
- 覆盖的面积 HDU - 1255 线段树+扫描线+离散化 求特定交叉面积
#include<cstdio> #include<map> #include<algorithm> using namespace std; ; struct N ...
随机推荐
- Android内嵌VLC实现播放网络视频,网络音频
1.在对应模块的build.gradle文件中,添加依赖 //VlC implementation "de.mrmaffen:vlc-android-sdk:2.0.6" 2.布局 ...
- c/c++ 标准顺序容器 容器的访问,删除 操作
c/c++ 标准顺序容器 容器的访问,删除 操作 pop_front:vector,string不支持 pop_back:forward_list不支持 知识点 1,front, back, at 成 ...
- C++多线程同步技巧(三)--- 互斥体
简介 Windows互斥对象机制. 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问,在线程同步与保证程序单体运行上都有相当大的用处. 代码 ...
- 通过一篇YAML来学习YAML
yaml 兼容 json,至今已发展至 1.2版.支持N多种编程语言.官网:http://www.yaml.org/ 格式在线校验:http://nodeca.github.io/js-yaml/ 下 ...
- Syntax error, parameterized types are only available if source level is 1.5 解决方案
在网上找了一个K-means算法的程序,打开,运行,出现了Syntax error,parameterized types are only available if source level is ...
- 我的游戏学习日志3——三国志GBA
我的游戏学习日志3——三国志GBA 三国志GBA由日本光荣公司1991~1995所推出<三国志>系列游戏,该作是光荣在GBA上推出的<三国志>系列作品的第一款.本游戏登场武将总 ...
- Alpha阶段 - 博客链接合集
Alpha阶段 - 博客链接合集 项目Github地址 安卓端(Stardust):https://github.com/StardustProject/Stardust 服务器端(Gravel):h ...
- flex布局快速成型(原创)
最近我根据一个UI设计,耗时3h快速实现较复杂页面布局,如上图.根据这份UI设计图,实现代码如下,暂不考虑具体细节,先以成型为主: <!DOCTYPE html> <html> ...
- 使用Intellij IDEA将web项目导出为war包
前言:IDEA导出war包的方式与MyEclipse有一点不同,使笔者在使用的时候有点困惑,在网上查阅相关资料的时候,发现其描述十分不清晰,于是就有了这篇随笔的诞生.话不多说,直接进入正题. 注:ID ...
- WPF设计の自定义窗体
效果图如下: 实现思路: 1.继承Window类 2.为自定义的CustomWindow类设计窗体样式(使用Blend很方便!) 3.为窗体增加最大最小化和关闭按钮,并实现鼠标拖拽改变窗体大小(使用D ...