hdu1255 矩阵的交 线段树+扫描线
/*
不是叶子节点 ,且cnt=1.注意这里,cnt=1确切的意义是什么,
应该是,可以确定,这个区间被完全覆盖了1次,
而有没有被完全覆盖两次或以上则不知道无法确定,那么怎么怎么办了,
只要加上t[lch].s + t[rch].s 即,看看左右孩子区间被覆盖了一次或以上的长度,
那么叠加在双亲上就是双亲被覆盖两次或以上的长度
*/ #include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 1005
struct segment
{
double l,r,h;
int f;
}s[maxn*];
struct node
{
int cnt;
double len1;//记录一次及以上的
double len2;//记录二次及以上的
}tree[maxn*];
double mark[maxn<<];
bool cmp(segment a,segment b)
{
return a.h<b.h;
}
void build(int l,int r,int rt)
{
tree[rt].cnt=;
tree[rt].len1=tree[rt].len2=;
if(l==r)
{
return ;
}
int m=(l+r)/;
build(lson);
build(rson);
}
/*
重点。
若该节点的cnt >= 2,说明被至少两条线段覆盖,那么len1=len2=区间长度。
若该节点的cnt == 1,说明该区间被一条线段覆盖,len1=区间长度,只要左右节点的len1有值,
那么那些长度一定是至少被覆盖两次的,因此len2为左右节点的len1之和。
若该节点的cnt = 0,说明没被完全覆盖,直接用其左右节点更新。
还要注意特判叶子节点。
*/
void getlen(int l,int r,int rt)
{
if(tree[rt].cnt>=)//>=2时很好理解,就是覆盖2次或以上,直接减一减
{
tree[rt].len1=mark[r+]-mark[l];
tree[rt].len2=mark[r+]-mark[l];
}
else if(tree[rt].cnt==)//此处需要注意
//由于cnt大于0,所以覆盖一次或以上的部分直接得到,而由于完全覆盖一次
//可能其他部分有覆盖,此时就可以根据左右孩子来,由于len1记录覆盖一次或
//以上的,因为已经完全覆盖了一次,只要加上左右孩子的一次或以上覆盖的值
//那么就是2次或以上覆盖的值。
{
tree[rt].len1=mark[r+]-mark[l];//因为覆盖一次,len1还要继续加
if(l == r)//由于覆盖一次,又只有一个l==r,所以len2为0
{
tree[rt].len2=;
}
else
{
tree[rt].len2=tree[rt<<].len1+tree[rt<<|].len1;
}
}
else if(tree[rt].cnt==)//为完全覆盖,根据孩子来。此处与上面等于1出相似,可以发现,如果为完全覆盖
//就可以根据左右孩子得到覆盖的,那cnt等于1时,要求覆盖2次的时候就也可以
//根据孩子来。
{
if(l == r)
tree[rt].len1=tree[rt].len2=;
else
{
tree[rt].len1=tree[rt<<].len1+tree[rt<<|].len1;
tree[rt].len2=tree[rt<<].len2+tree[rt<<|].len2;
}
}
}
void updata(int L,int R,int c,int l,int r,int rt)
{
if(l>=L&&R>=r)
{
tree[rt].cnt+=c;
getlen(l,r,rt);
return ;
}
int m=(l+r)/;
if(m>=L)
updata(L,R,c,lson);
if(R>m)
updata(L,R,c,rson);
getlen(l,r,rt);
}
int find(double val,int x,int y)
{
int l=x,r=y,m;
while(l<=r)
{
m=(l+r)/;
if(mark[m]==val)
return m;
else if(mark[m]>val)
r=m-;
else l=m+;
}
return -;
}
int main()
{
int t,n,i;
double x1,x2,y1,y2;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int m=;
for(i=;i<n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
s[m].l=x1;s[m].r=x2;s[m].h=y1;s[m].f=;mark[m++]=x1;
s[m].l=x1;s[m].r=x2;s[m].h=y2;s[m].f=-;mark[m++]=x2;
}
sort(s,s+m,cmp);
sort(mark,mark+m);
int k=;
for(i=;i<m;i++)
{
if(mark[i]!=mark[i-])
mark[k++]=mark[i];
}
/*
for(i=0;i<k;i++)
printf("%.2lf ",mark[i]);
printf("\n");
*/
build(,k-,);
double ans=;
for(i=;i<m;i++)
{
int ll=find(s[i].l,,k-);
int rr=find(s[i].r,,k-)-;
updata(ll,rr,s[i].f,,k-,);
ans+=(s[i+].h-s[i].h)*tree[].len2;
}
printf("%.2lf\n",ans);
}
}
hdu1255 矩阵的交 线段树+扫描线的更多相关文章
- hdu1255 覆盖的面积 线段树-扫描线
矩形面积并 线段树-扫描线裸题 #include<stdio.h> #include<string.h> #include<algorithm> #include& ...
- hdu1542矩阵的并 线段树+扫描线
求矩阵的并,也就是要求所有的面积.那可以吧总的图形按照矩阵来切割.使其为一块一块. 输入的时候用坐标表示,这里扫描线从下到上扫描.初始时让下面的边为1,上面的为-1: 用一条先从下面开始想上扫描.遇到 ...
- POJ 1151 Atlantis 矩形面积求交/线段树扫描线
Atlantis 题目连接 http://poj.org/problem?id=1151 Description here are several ancient Greek texts that c ...
- hdu 4052 线段树扫描线、奇特处理
Adding New Machine Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- hdu 1828 线段树扫描线(周长)
Picture Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- HDU 6096 String 排序 + 线段树 + 扫描线
String Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others) Problem De ...
- HDU 1828“Picture”(线段树+扫描线求矩形周长并)
传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...
- 【Codeforces720D】Slalom 线段树 + 扫描线 (优化DP)
D. Slalom time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...
- Codeforces VK CUP 2015 D. Closest Equals(线段树+扫描线)
题目链接:http://codeforces.com/contest/522/problem/D 题目大意: 给你一个长度为n的序列,然后有m次查询,每次查询输入一个区间[li,lj],对于每一个查 ...
随机推荐
- 分布式服务框架 Zookeeper(转)
分布式服务框架 Zookeeper -- 管理分布式环境中的数据 Zookeeper 分布式服务框架是 Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题 ...
- HDU 5057 Argestes and Sequence --树状数组(卡内存)
题意:给n个数字,每次两种操作: 1.修改第x个数字为y. 2.查询[L,R]区间内第D位为P的数有多少个. 解法:这题当时被卡内存了,后来看了下别人代码发现可以用unsigned short神奇卡过 ...
- 使用JspStudy集成环境快速部署jsp项目
1. 安装jdk 本人网盘资源:https://yunpan.cn/ckZLNbqxkDYYe (提取码:b5e8) 去jdk官网下载最新的jdk: http://www.oracle.com/tec ...
- AndroidStudio出现“Plugin is too old, please update to a more recent”问题
可能原因: 你AS版本不够高....能够更新的话你更新试下,不能更新删了最新的sdk,不要下载4.4以上的版本 解决方法如下 第一种,最简单,但是不推荐这么做 将build.gradle 里的类似 c ...
- ie6,ie7兼容性总结(转)
其实浏览器的不兼容,我们往往是各个浏览器对于一些标准的定义不一致导致的,因此,我们可以进行一些初始化,很多问题都很轻松解决. 下面是14条特殊情况仅供参考: 1. 文字本身的大小不兼容.同样是font ...
- MAC中设置android adb环境变量
1.找到android sdk的本地路径, adb命令在platform-tool下面,记为XXXX 我的路径是(/Applications/eclipse/android-sdk-mac_x86/p ...
- Kinect for Windows SDK开发初体验(一)环境配置
1.开发环境需求 (1).硬件需求 a.需要拥有双核,2.66GHz以上的CPU. b.显卡支持Microsoft DirectX 9.0c; c.2GB的内存 d.Kinect for Window ...
- [IIS][ASP.NET]“拒绝访问临时目录”的解决方法
开始以为是“C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files”文件夹权限的问题,但怎么设置这个权限也解决不 ...
- Nginx+UWSGI+Django配置全过程
重度参阅 原理+实战http://zhou123.blog.51cto.com/4355617/1688434 原理http://www.cnblogs.com/fnng/p/5268633.html ...
- 跳台阶 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
class Solution { public: int jumpFloor(int number) { ) ; ) ; )+jumpFloor(number-); } }; 如果先建立数组,然后利用 ...