自己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 覆盖的面积 (线段树扫描线+面积交)的更多相关文章

  1. HDU 1264 Counting Squares (线段树-扫描线-矩形面积并)

    版权声明:欢迎关注我的博客.本文为博主[炒饭君]原创文章,未经博主同意不得转载 https://blog.csdn.net/a1061747415/article/details/25471349 P ...

  2. hdu1255 覆盖的面积 线段树-扫描线

    矩形面积并 线段树-扫描线裸题 #include<stdio.h> #include<string.h> #include<algorithm> #include& ...

  3. HDU 4419 Colourful Rectangle --离散化+线段树扫描线

    题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何 ...

  4. poj1511,线段树扫描线面积

    经典题,线段树扫描线其实类似区间更新,一般的做法是想象一根扫描线从上扫到下或者从左扫到右,本题的做法是从上扫到下 只要扫到了一根水平线,就将其更新到线段树对应区间中,区间和它的子区间是独立更新的 #i ...

  5. HDU 1255 覆盖的面积 (线段树+扫描线+离散化)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 题意很清楚,就是让你求矩阵之间叠加层数大于1的矩形块的面积和. 因为n只有1000,所以我离散化 ...

  6. hdu 1255 覆盖的面积 (线段树处理面积覆盖问题(模板))

    http://acm.hdu.edu.cn/showproblem.php?pid=1255 覆盖的面积 Time Limit: 10000/5000 MS (Java/Others)    Memo ...

  7. HDU1255 覆盖的面积 —— 求矩形交面积 线段树 + 扫描线 + 离散化

    题目链接:https://vjudge.net/problem/HDU-1255 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input输入数据的第一行是一个正整数T(1<= ...

  8. HDU 1255 覆盖的面积 线段树+扫描线

    同 POJ1151 这次是两次 #include <iostream> #include <algorithm> #include <cstdio> #includ ...

  9. hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

随机推荐

  1. appearance 设置公共属性

    //设置公共TabBarItem 的属性 [UITabBarItem appearance] //设置公共NavigationBar 的属性 [UIBarButtonItem appearance]

  2. 自定义Spring Shell

    目录 概述 自定义内置命令 禁用内置命令 覆盖内置命令 自定义命令提示符 自定义命令行选项行为 自定义参数转换器 概述 官网:https://projects.spring.io/spring-she ...

  3. mysql数据库去除重复数据

    (一)最原始的方法: delete from test where id not in (select * from ((select min(id) from test group by(name) ...

  4. linux svn 更新地址

    进行你所工作的svn映射到本地的目录中.在终端下运行$svn switch --relocate http://oldPath http://newpath.系统提示输入用户名,密码.重新输入后,即可 ...

  5. android 蓝牙低耗能(LBE)技术介绍

    蓝牙低能耗(BLE)技术是低成本.短距离.可互操作的鲁棒性无线技术.工作在免许可的2.4GHz ISM射频频段.它从一開始就设计为超低功耗(ULP)无线技术. 它利用很多智能手段最大限度地减少功耗. ...

  6. 把flask部署到服务器

    1.新建一个wsgi.py文件 # -*- coding:utf-8 -*- import sys from os.path import abspath from os.path import di ...

  7. 【JMeter4.0学习(十)】之JMeter函数简单运用以及结合正则表达式提取器

    下面来简单的举个栗子: 首先,把函数和正则表达式提取器放在一块来介绍,如下所示: 1.结构完整展示,下面再一步一步创建添加: 2.添加线程组: 3.首先添加HTTP请求1 4.添加结果树后,运行后查看 ...

  8. ajax 和jsonp 不是一码事 细读详解

    由于Sencha Touch 2这种开发模式的特性,基本决定了它原生的数据交互行为几乎只能通过AJAX来实现. 当然了,通过调用强大的PhoneGap插件然后打包,你可以实现100%的Socket通讯 ...

  9. 【BZOJ3105】[cqoi2013]新Nim游戏 贪心+线性基

    [BZOJ3105][cqoi2013]新Nim游戏 Description 传统的Nim游戏是这样的:有一些火柴堆,每堆都有若干根火柴(不同堆的火柴数量可以不同).两个游戏者轮流操作,每次可以选一个 ...

  10. Scout YYF I (概率+矩阵快速幂)

    YYF is a couragous scout. Now he is on a dangerous mission which is to penetrate into the enemy's ba ...