题目大意:

给出N个立方体。

求一个三维空间中被包围三次的空间的体积之和。

思路分析:

发现Z的范围非常小。那么我们能够枚举Z轴,然后对 x y做扫描线。

并且不用枚举全部的Z ,仅仅须要将Z离散化之后枚举。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define maxn 2222
#define debug puts("fuck!")
#define lson num<<1,s,mid
#define rson num<<1|1,mid+1,e
typedef long long LL;
using namespace std; inline void scanf_(int &num){
char in;
bool neg=false;
while(((in=getchar()) > '9' || in<'0') && in!='-') ;
if(in=='-'){
neg=true;
while((in=getchar()) >'9' || in<'0');
}
num=in-'0';
while(in=getchar(),in>='0'&&in<='9')
num*=10,num+=in-'0';
if(neg)
num=0-num;
} struct node
{
int x1,y1,z1;
int x2,y2,z2;
void scan()
{
scanf_(x1);
scanf_(y1);
scanf_(z1);
scanf_(x2);
scanf_(y2);
scanf_(z2);
}
}cube[maxn]; struct line
{
int s,e,h,type;
bool operator < (const line &cmp)const
{
return h<cmp.h;
}
}scline[maxn<<1]; int len[maxn<<2][4];
int cov[maxn<<2];
int x[maxn];
int z[maxn];
int cntx,cntz,n; void init()
{
cntx=cntz=0;
} void pushup(int num,int s,int e)
{
if(cov[num]>=3)
{
len[num][3]=len[num][0];
len[num][1]=len[num][2]=0;
}
else if(cov[num]==2)
{
if(s==e)
{
len[num][1]=len[num][3]=0;
len[num][2]=len[num][0];
}
else
{
len[num][3]=len[num<<1][3]+len[num<<1|1][3]+len[num<<1][2]+len[num<<1|1][2]
+len[num<<1][1]+len[num<<1|1][1];
len[num][2]=len[num][0]-len[num][3];
len[num][1]=0;
}
}
else if(cov[num]==1)
{
if(s==e)
{
len[num][1]=len[num][0];
len[num][2]=len[num][3]=0;
}
else {
len[num][3]=len[num<<1][3]+len[num<<1|1][3]+len[num<<1][2]+len[num<<1|1][2];
len[num][2]=len[num<<1][1]+len[num<<1|1][1];
len[num][1]=len[num][0]-len[num][2]-len[num][3];
}
}
else
{
len[num][3]=len[num<<1][3]+len[num<<1|1][3];
len[num][2]=len[num<<1][2]+len[num<<1|1][2];
len[num][1]=len[num<<1][1]+len[num<<1|1][1];
}
}
void build(int num,int s,int e)
{
len[num][0]=x[e+1]-x[s];
len[num][1]=len[num][2]=len[num][3]=0;
cov[num]=0; if(s==e)return; int mid=(s+e)>>1;
build(lson);
build(rson);
} void update(int num,int s,int e,int l,int r,int val)
{
if(l<=s && r>=e)
{
cov[num]+=val; if(cov[num]>=3)
{
len[num][3]=len[num][0];
len[num][1]=len[num][2]=0;
}
else if(cov[num]==2)
{
if(s==e)
{
len[num][1]=len[num][3]=0;
len[num][2]=len[num][0];
}
else
{
len[num][3]=len[num<<1][3]+len[num<<1|1][3]+len[num<<1][2]+len[num<<1|1][2]
+len[num<<1][1]+len[num<<1|1][1];
len[num][2]=len[num][0]-len[num][3];
len[num][1]=0;
}
}
else if(cov[num]==1)
{
if(s==e)
{
len[num][1]=len[num][0];
len[num][2]=len[num][3]=0;
}
else {
len[num][3]=len[num<<1][3]+len[num<<1|1][3]+len[num<<1][2]+len[num<<1|1][2];
len[num][2]=len[num<<1][1]+len[num<<1|1][1];
len[num][1]=len[num][0]-len[num][2]-len[num][3];
}
}
else
{
len[num][3]=len[num<<1][3]+len[num<<1|1][3];
len[num][2]=len[num<<1][2]+len[num<<1|1][2];
len[num][1]=len[num<<1][1]+len[num<<1|1][1];
}
return ;
} int mid=(s+e)>>1; if(l<=mid)update(lson,l,r,val);
if(r>mid)update(rson,l,r,val); pushup(num,s,e);
} void solve(int kase)
{
build(1,0,cntx-2); LL ans=0;
for(int i=0;i<cntz-1;i++)
{
int cnt=0; for(int j=0;j<n;j++)
{
if(cube[j].z1<=z[i] && cube[j].z2>z[i])
{
scline[cnt].s=cube[j].x1;
scline[cnt].e=cube[j].x2;
scline[cnt].h=cube[j].y1;
scline[cnt++].type=1; scline[cnt].s=cube[j].x1;
scline[cnt].e=cube[j].x2;
scline[cnt].h=cube[j].y2;
scline[cnt++].type=-1;
}
} LL area=0;
sort(scline,scline+cnt); for(int j=0;j<cnt-1;j++)
{
int l=lower_bound(x,x+cntx,scline[j].s)-x;
int r=lower_bound(x,x+cntx,scline[j].e)-x; update(1,0,cntx-2,l,r-1,scline[j].type);
area+=(LL)len[1][3]*(scline[j+1].h-scline[j].h); }
int l=lower_bound(x,x+cntx,scline[cnt-1].s)-x;
int r=lower_bound(x,x+cntx,scline[cnt-1].e)-x;
update(1,0,cntx-2,l,r-1,scline[cnt-1].type);
ans+=area*(z[i+1]-z[i]);
}
printf("Case %d: %I64d\n",kase,ans);
}
int main()
{
int T;
scanf("%d",&T);
for(int cas=1;cas<=T;cas++)
{
init(); scanf("%d",&n); for(int i=0;i<n;i++)
{
cube[i].scan(); x[cntx++]=cube[i].x1;
x[cntx++]=cube[i].x2; z[cntz++]=cube[i].z1;
z[cntz++]=cube[i].z2;
} sort(x,x+cntx);
sort(z,z+cntz); cntx=unique(x,x+cntx)-x;
cntz=unique(z,z+cntz)-z; solve(cas);
}
return 0;
}

hdu 3642 Get The Treasury (三维的扫描线)的更多相关文章

  1. HDU 3642 Get The Treasury (线段树扫描线,求体积并)

    参考链接 : http://blog.csdn.net/zxy_snow/article/details/6870127 题意:给你n个立方体,求覆盖三次以上(包括三次)的区域的体积 思路:先将z坐标 ...

  2. hdu 3642 Get The Treasury(扫描线)

    pid=3642" style="">题目链接:hdu 3642 Get The Treasury 题目大意:三维坐标系,给定若干的长方体,问说有多少位置被覆盖3次 ...

  3. HDU 3642 - Get The Treasury - [加强版扫描线+线段树]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Others) Memory L ...

  4. HDU 3642 Get The Treasury 线段树+分层扫描线

    http://www.acmerblog.com/hdu-3642-get-the-treasury-6603.html 学习:三维就是把竖坐标离散化分层,每一层进行线段树二维面积并就好了

  5. HDU 3642 Get The Treasury (线段树扫描线)

    题意:给你一些长方体,问你覆盖三次及以上的体积有多大 首先我们观察x轴y轴一样很大,但是z轴很小,所以我们可以枚举z轴(-500,500),注意我们枚举的是每一段长度为一的z轴的xy轴的面积而不是点. ...

  6. hdu 3642 Get The Treasury

    Get The Treasury http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Othe ...

  7. HDU - 3642 Get The Treasury(线段树求体积交)

    https://cn.vjudge.net/problem/HDU-3642 题意 求立方体相交至少3次的体积. 分析 三维的呢..首先解决至少覆盖三次的问题.则用三个标记,更新时的细节要注意. 注意 ...

  8. HDU 3642 Get The Treasury ( 线段树 求长方体体积并 )

    求覆盖三次及其以上的长方体体积并. 这题跟 http://wenku.baidu.com/view/d6f309eb81c758f5f61f6722.html 这里讲的长方体体积并并不一样. 因为本题 ...

  9. Get The Treasury HDU - 3642(扫描线求三维面积交。。体积交)

    题意: ...就是求体积交... 解析: 把每一层z抽出来,计算面积交, 然后加起来即可..! 去看一下 二维面积交的代码 再看看这个三维面积交的代码.. down函数里 你发现了什么规律!!! 参考 ...

随机推荐

  1. Web字体库下载及转换工具

    1.字体现在网站: http://ztxz.org/ 2.Web字体在线格式转换器: http://www.freefontconverter.com/ 3.

  2. 一个PHP开发者总结的九条建议

    本文只是个人从实际开发经验中总结的一些东西,并不是什么名言警句,写出来有两个目的:一是时刻提醒自己要按照这些知识点来写自己代码,二是为了分享,说不定对你有用呢?万一,是吧... 1.首要意识:安全 大 ...

  3. eclipse中启动tomcat

    0.以下即使部署好,点小猫启动tomcat,有一个问题,修改jsp文件,本地tomcat中的此jsp并没有修改,如果右键项目启动,则会修改,不知道为什么 1. 首先发布项目,项目右键,run serv ...

  4. 从Select语句看Oracle查询原理(了解Oracle的查询机制)

    第一步:客户端把语句发给服务器端执行 当我们在客户端执行select语句时,客户端会把这条SQL语句发送给服务器端,让服务器端的进程来处理这语句.也就是说,Oracle客户端是不会做任何的操作,他的主 ...

  5. XMLHelper 类

     这个XMLHelper类中包括了XML文档的创建,文档节点和属性的读取,添加,修改,删除的方法功能的实现,有兴趣的朋友,可以进来看看,所有代码都在WebForm和WinForm中调试通过. 这是下面 ...

  6. C语言之头文件,static与const关键字

    [前言] 最近几个月在做一个C语言代码重构的项目,过程中也让我对之前在书本上学习到的东西有些补充和巩固,在本博中总结记录下,梳理下零碎的知识点和经验也加深印象,书写是为了更好地思考.平时也都是用印象笔 ...

  7. Neutron/ML2学习

    Neutron/ML2 Neutron ML2 模块层2(ml2)插件是一种允许OpenStack网络同时地利用在复杂现实数据中心发现的各种第二层网络技术的框架.目前它与存在的openvswitch. ...

  8. 使用BOOST BIND库提高C++程序性能

    Boost.Bind为函数和函数对象,值语义和指针提供语义了一致的语法.我们首先通过一些简单的例子来看看它的基本用法,之后我们会延伸到嵌套绑定以实现功能组合.理解bind用法的一个关键是理解占位符(p ...

  9. 关闭C#主窗体弹出是否关闭对话框

    在开发系统时,常常有这样一个问题,就是当关闭主窗体,也即退出系统时,如果想提示是否关闭,以免误操作,可以在主窗体的Main_FormClosing事件中添加一个对话框,代码如下: private vo ...

  10. 转型函数 Boolean()

    布尔值有2种可能的值true和false;但 ECMAScript中所有类型的值都有与这两个 Boolean 值 等价的值.要将一个值转换为其对应的 Boolean 值,可以调用转型函数 Boolea ...