HDU 1255 覆盖的面积 (线段树扫描线+面积交)
自己YY了一个的写法,不过时间复杂度太高了,网上的想法太6了
题意:给你一些矩阵,求出矩阵的面积并
首先按照x轴离散化线段到线段树上(因为是找连续区间,所以段建树更加好做)。
然后我们可以想一下怎样才能使面积相交呢?我们可以注意到如果矩阵入线出现超过一次就一定有面积相交,所以我们记录入线与出线,再排序y轴,从小到大(注意y轴等大时先进后出)扫描线段。
记录:总长度,当前一整段一起覆盖一次的长度,当前一整段一起覆盖超过一次的长度,当前一整段一起覆盖覆盖的次数(注意这一整段的情况不会更新到孩子节点)为什么是当前一整段且不更新呢?因为我们要计算的是插入这一段(入线或出线)后,所有的线覆盖超过一次的长度。如果仅仅计算入线中超过一次线覆盖的长度,就会少计算一些面积,原因是我们每次会把y轴更新,这样就还有一些不在现在入线这一段中却覆盖超过一次的线段没有统计。
入线:矩阵下方的x轴的线(按照y轴扫描),表示矩阵进入扫描线,开始计算
出现:矩阵上方的x轴的线(按照y轴扫描),表示矩阵已经出去,不能计算了
/*给一些矩阵求矩阵面积交:离散化x轴,排序y轴扫描,注意记录一个cover,关键在此cover表示仅仅次一连续段的覆盖情况们不要更新到孩子节点
而此时只需要记录区间覆盖两次及以上的长度是多少就好*/
#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
const int Max=<<;//每个矩形扫描时看做两条线
struct node
{
double len[];//线段本身长度,覆盖次数为1次,覆盖次数大于1次的线段的长度
int cover;//表示这一段被覆盖的次数
}segtr[Max];
struct nide
{
int typ;
double xx1,xx2,yy1;
}lin[Max];
map<double,int> mp;//快速找到某个x所对应的树上的点
double llin[Max];//离散化到树上对应节点
bool cmp(struct nide p1,struct nide p2)
{
if(p1.yy1==p2.yy1)
return p1.typ>p2.typ;//关键 同一个位置先进后出
return p1.yy1<p2.yy1;
}
void Create(int sta,int enn,int now)
{
segtr[now].cover=;
segtr[now].len[]=llin[enn]-llin[sta];
segtr[now].len[]=segtr[now].len[]=0.0;
if(sta+==enn)//为了处理连续段可能没有包含完整的情况采用段建树
return;
int mid=dir(sta+enn,);
int next=mul(now,);
Create(sta,mid,next);
Create(mid,enn,next|);
return;
}
void Upnow(int now,int sta,int enn)//主要的函数
{
int next=mul(now,);//注意现在的flag仅仅代表这一条线连续在一起的的情况,但是这一条线如果分成几段的话就不一定是这样的,即**这个flag并不代表这一线所以的情况**
if(segtr[now].cover>=)
{
segtr[now].len[]=0.0;
segtr[now].len[]=segtr[now].len[];
}
else if(segtr[now].cover==)//此线段被覆盖一次,则孩子节点的线段覆盖情况就应该都加一次,注意此点与孩子节点的覆盖次数不相干
{
if(sta+!=enn)
segtr[now].len[]=segtr[next].len[]+segtr[next|].len[]+segtr[next].len[]+segtr[next|].len[];
else
segtr[now].len[]=0.0;
segtr[now].len[]=segtr[now].len[]-segtr[now].len[];//len 1+2 == 0
}
else
{
if(sta+==enn)
{
segtr[now].len[]=0.0;
segtr[now].len[]=0.0;
}
else
{
segtr[now].len[]=segtr[next].len[]+segtr[next|].len[];
segtr[now].len[]=segtr[next].len[]+segtr[next|].len[];
}
}
return;
}
void Update(int sta,int enn,int now,int x,int y,int z)
{
if(sta>=x&&enn<=y)
{
segtr[now].cover+=z;
Upnow(now,sta,enn);//更新len
return;
}
int mid=dir(sta+enn,);
int next=mul(now,);
if(mid>x)
Update(sta,mid,next,x,y,z);
if(mid<y)
Update(mid,enn,next|,x,y,z);
Upnow(now,sta,enn);
return;
}
double Solve(int m,int cnt)
{
double ans=0.0;
sort(lin,lin+m,cmp);
Create(,cnt,);
for(int i=;i<m;i++)//按照y轴从前到后扫描
{
if(i)
ans+=segtr[].len[]*(lin[i].yy1-lin[i-].yy1);//添加后计算,注意计算的时候要延迟一次
Update(,cnt,,mp[lin[i].xx1],mp[lin[i].xx2],lin[i].typ);
}
return ans;
}
int main()
{
int t,n,m,cnt;
scanf("%d",&t);
while(t--)
{
mp.clear();
scanf("%d",&n);
m=;
for(int i=;i<n;i++)
{
scanf("%lf %lf %lf %lf",&lin[m].xx1,&lin[m].yy1,&lin[m+].xx2,&lin[m+].yy1);
lin[m].xx2=lin[m+].xx2,lin[m+].xx1=lin[m].xx1;
lin[m].typ=,lin[m+].typ=-;//进线与出线
mp[lin[m].xx1]=,mp[lin[m].xx2]=;
m+=;
}
cnt=;//从1开始,关键关键
for(map<double,int>::iterator it=mp.begin();it!=mp.end();++it)
{
it->second=cnt;
llin[cnt++]=it->first;
}
cnt--;//注意不能多
printf("%.2f\n",Solve(m,cnt));
}
return ;
}
HDU 1255 覆盖的面积 (线段树扫描线+面积交)的更多相关文章
- HDU 1264 Counting Squares (线段树-扫描线-矩形面积并)
版权声明:欢迎关注我的博客.本文为博主[炒饭君]原创文章,未经博主同意不得转载 https://blog.csdn.net/a1061747415/article/details/25471349 P ...
- hdu1255 覆盖的面积 线段树-扫描线
矩形面积并 线段树-扫描线裸题 #include<stdio.h> #include<string.h> #include<algorithm> #include& ...
- HDU 4419 Colourful Rectangle --离散化+线段树扫描线
题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何 ...
- poj1511,线段树扫描线面积
经典题,线段树扫描线其实类似区间更新,一般的做法是想象一根扫描线从上扫到下或者从左扫到右,本题的做法是从上扫到下 只要扫到了一根水平线,就将其更新到线段树对应区间中,区间和它的子区间是独立更新的 #i ...
- HDU 1255 覆盖的面积 (线段树+扫描线+离散化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 题意很清楚,就是让你求矩阵之间叠加层数大于1的矩形块的面积和. 因为n只有1000,所以我离散化 ...
- hdu 1255 覆盖的面积 (线段树处理面积覆盖问题(模板))
http://acm.hdu.edu.cn/showproblem.php?pid=1255 覆盖的面积 Time Limit: 10000/5000 MS (Java/Others) Memo ...
- HDU1255 覆盖的面积 —— 求矩形交面积 线段树 + 扫描线 + 离散化
题目链接:https://vjudge.net/problem/HDU-1255 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input输入数据的第一行是一个正整数T(1<= ...
- HDU 1255 覆盖的面积 线段树+扫描线
同 POJ1151 这次是两次 #include <iostream> #include <algorithm> #include <cstdio> #includ ...
- hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
随机推荐
- 我的_vimrc文件
""""""""""""""""&quo ...
- iOS swift NSClassFromString将字符串转换成类名
在oc中将字符串转换成类名直接调用NSClassFromString("classname")即可,但是到了swift中变的麻烦多了 swift中如果要将字符串转换为类型需要以下几 ...
- Android程序的打包和安装
当我们使用Android Studio的时候,这些步骤都交给它去做了. 编译 classes.dex 文件 编译 resources.arsc 文件 生成资源索引表resources.arsc. 把r ...
- 从头认识java-17.5 堵塞队列(以生产者消费者模式为例)
这一章节我们来讨论一下堵塞队列.我们以下将通过生产者消费者模式来介绍堵塞队列. 1.什么是堵塞队列?(摘自于并发编程网对http://tutorials.jenkov.com/java-concurr ...
- poj1066(叉乘的简单应用)
做完了才发现,好像没有人和我的做法一样的,不过我怎么都觉得我的做法还是挺容易想的. 我的做法是: 把周围的方框按顺时针编号,然后对于每一条边,如果点出现在边的一侧,则把另一侧所有的点加1,这样最后统计 ...
- zabbix_get 命令介绍
zabbix_get 是 zabbix 服务端的一个命令,用于检测 agent 端的配置是否正确,可以很方便地知道 key 是否能正常获取到数据,在测试自定义监控的时候特别有用 [root@crazy ...
- ASP向上取整
<%Function Ceil(value) Dim return return = int(value) Cei2=value-return if Cei2>0 ...
- Jquery点击事件出发顺序
鼠标点击触发事件执行顺序: mouse down -> mouse up -> click 键盘点击出发事件执行顺序: 点击后马上抬起:key down -> key press - ...
- http请求(get 和 post 请求)与响应
版权声明:欢迎转载 https://blog.csdn.net/chenmoquan/article/details/36656101 一.http请求 http请求基本格式 ============ ...
- (扫盲)RPC远程过程调用
https://blog.csdn.net/mindfloating/article/details/39473807 https://blog.csdn.net/mindfloating/artic ...