hdu1255(线段树——矩形面积交)
题目连接: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(线段树——矩形面积交)的更多相关文章
- HDU - 1255 覆盖的面积 (线段树求面积交)
https://cn.vjudge.net/problem/HDU-1255 题意 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 分析 求面积并的题:https://www.cnbl ...
- HDU 1255 覆盖的面积 (线段树扫描线+面积交)
自己YY了一个的写法,不过时间复杂度太高了,网上的想法太6了 题意:给你一些矩阵,求出矩阵的面积并 首先按照x轴离散化线段到线段树上(因为是找连续区间,所以段建树更加好做). 然后我们可以想一下怎样 ...
- HDU 1542:Atlantis(扫描线+线段树 矩形面积并)***
题目链接 题意 给出n个矩形,求面积并. 思路 使用扫描线,我这里离散化y轴,按照x坐标从左往右扫过去.离散化后的y轴可以用线段树维护整个y上面的线段总长度,当碰到扫描线的时候,就可以统计面积.这里要 ...
- hdu1542(线段树——矩形面积并)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1542 分析:离散化+扫描线+线段树 #pragma comment(linker,"/STA ...
- poj 1151 Atlantis (离散化 + 扫描线 + 线段树 矩形面积并)
题目链接题意:给定n个矩形,求面积并,分别给矩形左上角的坐标和右上角的坐标. 分析: 映射到y轴,并且记录下每个的y坐标,并对y坐标进行离散. 然后按照x从左向右扫描. #include <io ...
- 2015 UESTC 数据结构专题E题 秋实大哥与家 线段树扫描线求矩形面积交
E - 秋实大哥与家 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/59 De ...
- HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)
链接:线段树求矩形面积并 扫描线+离散化 1.给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 2.看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同. 求面积时,用被覆 ...
- hdu 1542 线段树扫描(面积)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Su ...
- 2019计蒜之道初赛4 B. 腾讯益智小游戏—矩形面积交(简单)(矩形交集)
B. 腾讯益智小游戏—矩形面积交(简单) 1000ms 262144K 腾讯游戏开发了一款全新的编程类益智小游戏,最新推出的一个小游戏题目是关于矩形面积交的.聪明的你能解出来吗?看下面的题目接招吧 ...
随机推荐
- 论文阅读笔记 - YARN : Architecture of Next Generation Apache Hadoop MapReduceFramework
作者:刘旭晖 Raymond 转载请注明出处 Email:colorant at 163.com BLOG:http://blog.csdn.net/colorant/ 更多论文阅读笔记 http:/ ...
- psl/sql本地与远程连接配置
一:下载Oracleclient 下载地址:http://www.oracle.com/technetwork/database/features/instant-client/index-09748 ...
- hdu4707 Pet
Pet Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissio ...
- MySQL 採用Xtrabackup对数据库进行全库备份
1,xtrabackup简单介绍 关于数据库备份以及备份工具.參考:http://blog.itpub.net/26230597/viewspace-1460065/,这里来介绍xtrabackup已 ...
- windows系统port监听
通常情况下.假设想发现全部已经使用的和正在监听的port,我们能够使用netstat命令. netstat并不是一个port扫描工具.假设你想扫描计算机开放了哪些port的话.建议使用本文介绍的方法. ...
- android之写文件到sd卡
1.main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:a ...
- QT 多线程程序设计(也有不少例子)
QT通过三种形式提供了对线程的支持.它们分别是,一.平台无关的线程类,二.线程安全的事件投递,三.跨线程的信号-槽连接.这使得开发轻巧的多线程Qt程序更为容易,并能充分利用多处理器机器的优势.多线程编 ...
- 14.3.2.1 Transaction Isolation Levels 事务隔离级别
14.3.2 InnoDB Transaction Model InnoDB 事务模型 14.3.2.1 Transaction Isolation Levels 事务隔离级别 14.3.2.2 au ...
- 第二章排错的工具:调试器Windbg(上)
感谢博主 http://book.51cto.com/art/200711/59731.htm <Windows用户态程序高效排错>第二章主要介绍用户态调试相关的知识和工具.本文主要讲了排 ...
- SilkTest Q&A 5
Q41.VerifyBitmap的问题. 我正在使用函数VerifyBitmap比较位置,边,颜色等,例如: Window.VerifyBitmap("Position.bmp", ...