hdu 3642 Get The Treasury (三维的扫描线)
题目大意:
给出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 (三维的扫描线)的更多相关文章
- HDU 3642 Get The Treasury (线段树扫描线,求体积并)
参考链接 : http://blog.csdn.net/zxy_snow/article/details/6870127 题意:给你n个立方体,求覆盖三次以上(包括三次)的区域的体积 思路:先将z坐标 ...
- hdu 3642 Get The Treasury(扫描线)
pid=3642" style="">题目链接:hdu 3642 Get The Treasury 题目大意:三维坐标系,给定若干的长方体,问说有多少位置被覆盖3次 ...
- HDU 3642 - Get The Treasury - [加强版扫描线+线段树]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Others) Memory L ...
- HDU 3642 Get The Treasury 线段树+分层扫描线
http://www.acmerblog.com/hdu-3642-get-the-treasury-6603.html 学习:三维就是把竖坐标离散化分层,每一层进行线段树二维面积并就好了
- HDU 3642 Get The Treasury (线段树扫描线)
题意:给你一些长方体,问你覆盖三次及以上的体积有多大 首先我们观察x轴y轴一样很大,但是z轴很小,所以我们可以枚举z轴(-500,500),注意我们枚举的是每一段长度为一的z轴的xy轴的面积而不是点. ...
- hdu 3642 Get The Treasury
Get The Treasury http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Othe ...
- HDU - 3642 Get The Treasury(线段树求体积交)
https://cn.vjudge.net/problem/HDU-3642 题意 求立方体相交至少3次的体积. 分析 三维的呢..首先解决至少覆盖三次的问题.则用三个标记,更新时的细节要注意. 注意 ...
- HDU 3642 Get The Treasury ( 线段树 求长方体体积并 )
求覆盖三次及其以上的长方体体积并. 这题跟 http://wenku.baidu.com/view/d6f309eb81c758f5f61f6722.html 这里讲的长方体体积并并不一样. 因为本题 ...
- Get The Treasury HDU - 3642(扫描线求三维面积交。。体积交)
题意: ...就是求体积交... 解析: 把每一层z抽出来,计算面积交, 然后加起来即可..! 去看一下 二维面积交的代码 再看看这个三维面积交的代码.. down函数里 你发现了什么规律!!! 参考 ...
随机推荐
- wpf Content数据绑定StringFormat起作用的原理和解决(转)
1.简单示例: <Window x:Class="WpfOne.Bind.Bind6" xmlns="http://schemas.microsoft.com/wi ...
- 利用Range改变光标位置
先上代码,代码取自网上某插件中 function caret(begin, end) { if (this.length == 0) return; if (typeof begin == 'numb ...
- Ajax数据格式,html,xml,json
1. 2. 3. 4. 5. 6. 7. 8. 9.
- OC中的单例设计模式及单例的宏抽取
// 在一个对象需要重复使用,并且很频繁时,可以对对象使用单例设计模式 // 单例的设计其实就是多alloc内部的allocWithZone下手,重写该方法 #pragma Person.h文件 #i ...
- 使用PPRevealSideViewController实现侧滑效果
使用起来还是比较简单的, 主要是几个步骤 AppDelegate.m - (BOOL)application:(UIApplication *)application didFinishLaunchi ...
- terminal命令
新建一个文件并写入内容: echo hello world > a.txt (每次echo都会重写文件) 新建文件: touch a.txt 新建目录: mkdir work 用vim打开文件 ...
- JS键盘的键码(event.keyCode)
keycode 8 = BackSpace BackSpace keycode 9 = Tab Tab keycode 12 = Clear keycode 13 = Enter keycode 16 ...
- 关于Chrome(谷歌浏览器)对docume,准确获取网页客户区的宽高、滚动条宽高、滚动条Left和Top
对于document.compatMode,很多朋友可能都根我一样很少接触,知道他的存在却不清楚他的用途.今天在ext中看到 document.compatMode的使用,感觉这个对于我们开发兼容性的 ...
- python的bind函数
# -*- coding:utf-8 -*- class Functor(object): def __init__(self, func, index=0, *args, **kwargs): se ...
- C语言笔记(枚举)
关于枚举,在我以前写程序的时候,几乎是没有使用过的,只是偶尔会在一下别人写的驱动库中有看到过.今天看了朱老师的视频,准备将枚举相关的东西总结一下. 一.关于枚举,你需要知道 (1)在C语言中就是一些符 ...