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 ...
随机推荐
- GitHub for window 使用教程
Git是目前最先进的分布式版本控制系统,作为一个程序员,我们需要掌握其用法. 一:下载GitHub for Windows 二:安装GitHub 下载之后点击进行安装过程,安装之后桌面上会有两个 ...
- 【NOI2015】【寿司晚宴】【状压DP】
Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴. 小 G 和小 W 作为參加 NOI 的选手,也被邀请參加了寿司晚宴. 在晚宴上,主办方为大家提供了 n−1 种不 ...
- Lua基本函数库 【转】
转自:http://www.cnblogs.com/whiteyun/archive/2009/08/12/1543184.html 基本函数库为Lua内置的函数库,不需要额外装载 assert (v ...
- Unity3d多人在线教程
[转载]Unity3d多人在线教程 (2013-02-25 16:02:49) 转载▼ 标签: 转载 原文地址:Unity3d多人在线教程作者:lsy0031 Unity 多个玩家开发教程 Uni ...
- [译]GLUT教程 - 整合代码5
Lighthouse3d.com >> GLUT Tutorial >> Extras >> The Code So Far V 该代码与位图字体的代码类似.区别是 ...
- 高度平衡树 -- AVL 树
Scheme 的表达, 优雅. #lang scheme ( define nil '() ) ( define ( root tree )( car tree ) ) ( define ( left ...
- 大型网站技术学习-2. 云计算之OpenStack简述
上一章讲,虚拟化能够充分的利用资源,带来各种各样的好处. 当一个网站不大,只需要四五台机器就可以支撑的时候,可以采用手工的方式虚拟机,但是当网站流量很高,需要成千上万台机器的时候,那就非常不方便了. ...
- xml初学简单介绍
什么是XML? 1.全称Extensible Markup Language,可扩展标记语言,W3C组织公布. 2.XML用来保存有一定结构关系的数据. 3.标签的嵌套,实质是一串字符串. 4.跨平台 ...
- 【Mac系统 + Python + Django】之开发一个发布会系统【Django视图(二)】
此学习资料是通过虫师的python接口自动化出的书学习而来的,在此说明一下,想学习更多的自动化的同学可以找虫师的博客园,非广告,因为我python+selenium自动化也是跟虫师学的,学习效果很好的 ...
- FastDFS分布文件系统
FastDFS是为互联网应用量身定做的一套分布式文件存储系统,非常适合用来存储用户图片.视频.文档等文件.对于互联网应用,和其他分布式文件系统相比,优势非常明显.具体情况大家可以看相关的介绍文档,包括 ...