题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1255

题意:求N个矩形中,求被覆盖至少俩次的面积和

分析:覆盖两次即col[rt]>=2就好。一开始将线段pushdown到叶子节点,根据col[rt]>=2才pushup上来,差点超时了,其实可以lazy标志,整段更新的,只是没想到而已。

用sum[rt][0]表示该节点rt代表的线段被覆盖一次的长度之和,则

if(col[rt])sum[rt][0]=pos[r+1]-pos[l];//整段被覆盖,全加上
else if(l==r)sum[rt][0]=0;//叶子节点没有子孙节点的覆盖传递上来,所以清零
else sum[rt][0]=sum[rt<<1][0]+sum[rt<<1|1][0];//加上子孙节点被覆盖着的长度

同理sum[rt][1]表示该节点rt代表的线段被覆盖两次的长度之和。则

if(col[rt]>1)sum[rt][1]=sum[rt][0];//整段被覆盖两次以上,全加上
else if(l==r)sum[rt][1]=0;//叶子节点没有子孙节点的覆盖两次的长度传递上来,故清零
else if(col[rt]==1)sum[rt][1]=sum[rt<<1][0]+sum[rt<<1|1][0];//加上之前子孙节点上被覆盖一次的长度,刚好共两次(覆盖一次的长度一定大于覆盖一次的)
else sum[rt][1]=sum[rt<<1][1]+sum[rt<<1|1][1];//加上子孙节点覆盖两次的总长度

如果题目求覆盖3次,4次都可以以此类推pushup上来。

成段更新(327ms)

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 10007
#define inf 0x3f3f3f3f
#define N 2015
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std; double pos[*N];
struct seg
{
double l,r,h;
int v;
seg(){}
seg(double l,double r,double h,int v):l(l),r(r),h(h),v(v){}
bool operator <(const seg a)const
{
return h<a.h;
}
}s[*N];
int n,col[N<<];
double sum[N<<][]; 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 l,int r,int rt)
{
if(col[rt])sum[rt][]=pos[r+]-pos[l];
else if(l==r)sum[rt][]=;
else sum[rt][]=sum[rt<<][]+sum[rt<<|][]; if(col[rt]>)sum[rt][]=sum[rt][];
else if(l==r)sum[rt][]=;
else if(col[rt]==)sum[rt][]=sum[rt<<][]+sum[rt<<|][];
else sum[rt][]=sum[rt<<][]+sum[rt<<|][];
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
col[rt]+=c;
Pushup(l,r,rt);
return;
}
int m=(l+r)>>;
if(L<=m)update(L,R,c,l,m,rt<<);
if(m<R)update(L,R,c,m+,r,rt<<|);
Pushup(l,r,rt);
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int i,k;
for(i=,k=; i<n; i++)
{
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
pos[k]=x1;
s[k++]=seg(x1,x2,y1,);
pos[k]=x2;
s[k++]=seg(x1,x2,y2,-);
}
sort(pos,pos+k);
sort(s,s+k);
int m=;
for(i=; i<k; i++)
if(pos[i]!=pos[i-])
pos[m++]=pos[i];
double res=;
for(i=; i<k; i++)
{
int l=bin(s[i].l,,m-);
int r=bin(s[i].r,,m-)-;
update(l,r,s[i].v,,m-,);
res += sum[][]*(s[i+].h - s[i].h);
}
printf("%.2lf\n",res);
}
return ;
}

比较耗时的暴力方法,都pushdown到叶子节点(1138ms):

#pragma comment(linker,"/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 10007
#define inf 0x3f3f3f3f
#define N 2015
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
struct line
{
double l,r,h;
int d;
line(){}
line(double l,double r,double h,int d):l(l),r(r),h(h),d(d){}
bool operator<(const line &a)const
{
return h<a.h;
}
}s[N];
double sum[N<<],has[N];
int col[N<<];
void Pushup(int l,int r,int rt)
{
if(col[rt]>)sum[rt]=has[r+]-has[l];
else if(l==r)sum[rt]=;
else sum[rt]=sum[rt<<]+sum[rt<<|];
}
void Pushdown(int d,int l,int r,int rt)
{
if(l==r)
{
col[rt]+=d;
Pushup(l,r,rt);return;
}
int m=(l+r)>>;
Pushdown(d,lson);
Pushdown(d,rson);
Pushup(l,r,rt);
}
void update(int L,int R,int d,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
Pushdown(d,l,r,rt);
return;
}
int m=(l+r)>>;
if(L<=m)update(L,R,d,lson);
if(m<R)update(L,R,d,rson);
Pushup(l,r,rt);
} int bin(double key,double a[],int n)
{
int l=,r=n-;
while(l<=r)
{
int m=(l+r)>>;
if(a[m]==key)return m;
if(a[m]>key)r=m-;
else l=m+;
}
return -;
}
int main()
{
int n,T;
double x1,y1,x2,y2;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int k=;
for(int i=;i<n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
has[k]=x1;
s[k++]=line(x1,x2,y1,);
has[k]=x2;
s[k++]=line(x1,x2,y2,-);
}
sort(s,s+k);
sort(has,has+k);
int m=;
for(int i=;i<k;i++)
if(has[i]!=has[i-])has[m++]=has[i];
double ans=;
for(int i=;i<k;i++)
{
int L=bin(s[i].l,has,m);
int R=bin(s[i].r,has,m)-;
update(L,R,s[i].d,,m-,);
ans+=sum[]*(s[i+].h-s[i].h);
}
printf("%.2lf\n",ans);
}
}

hdu1255(线段树——矩形面积交)的更多相关文章

  1. HDU - 1255 覆盖的面积 (线段树求面积交)

    https://cn.vjudge.net/problem/HDU-1255 题意 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 分析 求面积并的题:https://www.cnbl ...

  2. HDU 1255 覆盖的面积 (线段树扫描线+面积交)

    自己YY了一个的写法,不过时间复杂度太高了,网上的想法太6了  题意:给你一些矩阵,求出矩阵的面积并 首先按照x轴离散化线段到线段树上(因为是找连续区间,所以段建树更加好做). 然后我们可以想一下怎样 ...

  3. HDU 1542:Atlantis(扫描线+线段树 矩形面积并)***

    题目链接 题意 给出n个矩形,求面积并. 思路 使用扫描线,我这里离散化y轴,按照x坐标从左往右扫过去.离散化后的y轴可以用线段树维护整个y上面的线段总长度,当碰到扫描线的时候,就可以统计面积.这里要 ...

  4. hdu1542(线段树——矩形面积并)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1542 分析:离散化+扫描线+线段树 #pragma comment(linker,"/STA ...

  5. poj 1151 Atlantis (离散化 + 扫描线 + 线段树 矩形面积并)

    题目链接题意:给定n个矩形,求面积并,分别给矩形左上角的坐标和右上角的坐标. 分析: 映射到y轴,并且记录下每个的y坐标,并对y坐标进行离散. 然后按照x从左向右扫描. #include <io ...

  6. 2015 UESTC 数据结构专题E题 秋实大哥与家 线段树扫描线求矩形面积交

    E - 秋实大哥与家 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/59 De ...

  7. HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)

    链接:线段树求矩形面积并 扫描线+离散化 1.给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 2.看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同. 求面积时,用被覆 ...

  8. hdu 1542 线段树扫描(面积)

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

  9. 2019计蒜之道初赛4 B. 腾讯益智小游戏—矩形面积交(简单)(矩形交集)

    B. 腾讯益智小游戏—矩形面积交(简单) 1000ms 262144K   腾讯游戏开发了一款全新的编程类益智小游戏,最新推出的一个小游戏题目是关于矩形面积交的.聪明的你能解出来吗?看下面的题目接招吧 ...

随机推荐

  1. 南京三星面试准备3--数组&基础数据结构

    1.用递归颠倒一个栈. void PushToBottom(stack<int> &mystack,int num) { if(mystack.size()==0) { mysta ...

  2. Python 技巧

    1.根据路径导入模块 如果想引用指定路径下的某个模块,则需要使用sys.path.append("module_directory") 来把这个路径添加到sys下,这就涉及到Pyt ...

  3. CWnd中PreCreateWindow、PreSubclassWindow、SubclassWindow的区别

    http://blog.csdn.net/swimmer2000/archive/2007/10/30/1856213.aspx MFC(VC6.0)的CWnd及其子类中,有如下三个函数:     / ...

  4. 怎样使用jstack诊断Java应用程序故障(转)

    最近一段时间,我们的生产系统升级频繁出现故障,具体故障现象是启动后10来分钟就出现交易缓慢,处理线程耗尽等现象,并且故障发生的频率蛮高的.经过详细的诊断和排查,终于发现了问题,是groovy在osgi ...

  5. Problem E: Erratic Ants

    这个题没过……!题意:小蚂蚁向四周走,让你在他走过的路中寻找最短路,其中可以反向主要思路:建立想对应的图,寻找最短路径,其中错了好多次,到最后时间没过(1.没有考录反向2.没有考虑走过的路要标记……! ...

  6. 四个机器学习一步一步入门约束波尔兹曼机RBM

  7. 让工程师爱上CMM,实现管理于无形 --- 中标软件CMMI L5之路 (2/2)

    上节:见 http://blog.csdn.net/sztiger168/article/details/9142069 使用 青铜器RDM在2011年正式在中标软件上线,将研发业务全面流程化,完全支 ...

  8. [Android学习笔记]Android向下兼

    Android向下兼容的思路:使用高版本的API,在运行时判断真实运行平台的API版本,根据不同版本做不同的处理 关键类:Build.class里面定义了API版本相关信息 内部类:VERSION定义 ...

  9. POJ 2632 Crashing Robots(较为繁琐的模拟)

    题目链接:http://poj.org/problem?id=2632 题目大意:题意简单,N个机器人在一个A*B的网格上运动,告诉你机器人的起始位置和对它的具体操作,输出结果: 1.Robot i ...

  10. 用Stack实现对多线程的管理范例

    多线程就是并发技术,当线程数量超过一定数量时,系统响应就会变慢,所以就必须对线程数量进行控制,那么采用哪种控制方法呢?采用Stack类模仿堆栈,之所以说是模仿,就是因为Stack类毕竟不是真实的堆栈, ...