HDU 3642 - Get The Treasury - [加强版扫描线+线段树]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Jack can’t get the total volume of the treasury because these regions don’t always contain treasury. Through years of experience, he discovers that if a region is detected that may have treasury at more than two different spots, the region really exist treasure. And now Jack only wants to know the minimum volume of the treasury.
Now Jack entrusts the problem to you.
Each test case is given in some lines. In the first line there is an integer n (1 ≤ n ≤ 1000), the number of spots on the surface of the earth that he had detected. Then n lines follow, every line contains six integers x1, y1, z1, x2, y2 and z2, separated by a space. The absolute value of x and y coordinates of the vertices is no more than 106, and that of z coordinate is no more than 500.
题意:
给定一些长方体,求这些长方体相交至少3次的体积。
题解:
z坐标的范围 [-500, 500],比较小,所以可以枚举 z平面,用类似于扫描线扫描二维图形的方式,用扫描面扫描整个三维图形,而这些扫描面,就是所有长方体的上下平面,
那么,每个我们扫描得到的截面,就可以按照HDU1542里那样的普通的二维扫描线+线段树来做,求出这样一个截面上,重叠三次及以上的面积有多大,
同时,不难想到,若我们把长方体竖直的四个侧面,看成“下闭上开”(下沿取得到,上沿取不到)的话,当我们枚举到某一个平面 $z_i$ 时,该平面截得的截面,在区间 $\left[ {z_i ,z_{i + 1} } \right)$ 都是不会变动的,这个和普通的二维扫描线+线段树的道理是一样的。
故,枚举到某一个平面 $z_i$ 时,该平面截得的截面积,乘上高度 ${z_{i + 1} - z_i }$ 之后,就是整个“3+次重叠体”在三维区间 $\left[ {z_i ,z_{i + 1} } \right)$ 内的体积。
AC代码:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std; const int maxn=;
const int maxz=; int n; vector<int> x;
inline int getidx(int val){return lower_bound(x.begin(),x.end(),val)-x.begin();} vector<int> z; int tot;
struct Segment
{
int x1,x2,y;
int z1,z2;
int flag;
bool operator <(const Segment &oth)const{
return y<oth.y;
}
}segment[*maxn],tmp[*maxn]; /********************************* Segment Tree - st *********************************/
struct Node{
int l,r;
int s;
int once,twice,more;
void show()
{
printf("l=%d r=%d s=%d once=%d twice=%d more=%d\n",l,r,s,once,twice,more);
}
}node[*maxn];
void pushup(int rt)
{
int ls=rt*,rs=rt*+;
if(node[rt].s>)
{
node[rt].more=x[node[rt].r+]-x[node[rt].l];
node[rt].once=node[rt].twice=;
}
else if(node[rt].s==)
{
if(node[rt].l==node[rt].r)
{
node[rt].more=;
node[rt].twice=x[node[rt].r+]-x[node[rt].l];
node[rt].once=;
}
else
{
node[rt].more=node[ls].once+node[ls].twice+node[ls].more+node[rs].once+node[rs].twice+node[rs].more;
node[rt].twice=x[node[rt].r+]-x[node[rt].l]-node[rt].more;
node[rt].once=;
}
}
else if(node[rt].s==)
{
if(node[rt].l==node[rt].r)
{
node[rt].more=;
node[rt].twice=;
node[rt].once=x[node[rt].r+]-x[node[rt].l];
}
else
{
node[rt].more=node[ls].twice+node[ls].more+node[rs].twice+node[rs].more;
node[rt].twice=node[ls].once+node[rs].once;
node[rt].once=x[node[rt].r+]-x[node[rt].l]-node[rt].more-node[rt].twice;
}
}
else
{
if(node[rt].l==node[rt].r)
{
node[rt].more=;
node[rt].twice=;
node[rt].once=;
}
else
{
node[rt].more=node[ls].more+node[rs].more;
node[rt].twice=node[ls].twice+node[rs].twice;
node[rt].once=node[ls].once+node[rs].once;
}
}
//printf("now pushup rt=%d\t",rt); node[rt].show();
}
void build(int rt,int l,int r)
{
if(l>r) return;
node[rt].l=l; node[rt].r=r;
node[rt].s=;
node[rt].once=node[rt].twice=node[rt].more=;
if(l==r) return;
else
{
int mid=l+(r-l)/;
build(rt*,l,mid);
build(rt*+,mid+,r);
pushup(rt);
}
}
void update(int root,int st,int ed,int val)
{
if(st>node[root].r || ed<node[root].l) return;
if(st<=node[root].l && node[root].r<=ed)
{
node[root].s+=val;
pushup(root);
}
else
{
update(root*,st,ed,val);
update(root*+,st,ed,val);
pushup(root);
}
}
/********************************* Segment Tree - st *********************************/ int main()
{
int T;
scanf("%d",&T);
for(int kase=;kase<=T;kase++)
{
scanf("%d",&n); x.clear();
z.clear();
tot=;
for(int i=;i<=n;i++)
{
int x1,y1,z1,x2,y2,z2;
scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2); segment[tot].x1=x1; segment[tot].x2=x2; segment[tot].y=y1;
segment[tot].z1=z1; segment[tot].z2=z2;
segment[tot].flag=;
tot++; segment[tot].x1=x1; segment[tot].x2=x2; segment[tot].y=y2;
segment[tot].z1=z1; segment[tot].z2=z2;
segment[tot].flag=-;
tot++; x.push_back(x1);
x.push_back(x2);
z.push_back(z1);
z.push_back(z2);
} sort(x.begin(),x.end());
x.erase(unique(x.begin(),x.end()),x.end()); sort(z.begin(),z.end());
z.erase(unique(z.begin(),z.end()),z.end()); ll ans=;
for(int i=;i<z.size()-;i++)
{
//printf("now z=%d\n",z[i]);
int cnt=;
for(int j=;j<tot;j++) if(segment[j].z1<=z[i] && segment[j].z2>z[i]) tmp[cnt++]=segment[j];
sort(tmp,tmp+cnt); build(,,x.size());
ll area=;
for(int j=;j<cnt-;j++)
{
int l=getidx(tmp[j].x1);
int r=getidx(tmp[j].x2);
//printf("now update y=%d [%d,%d](%d,%d) += %d\n",tmp[j].y,x[l],x[r],l,r-1,tmp[j].flag);
update(,l,r-,tmp[j].flag);
area+=(ll)node[].more*(tmp[j+].y-tmp[j].y);
}
ans+=area*(z[i+]-z[i]);
} printf("Case %d: %I64d\n",kase,ans);
}
}
HDU 3642 - Get The Treasury - [加强版扫描线+线段树]的更多相关文章
- HDU 3265/POJ 3832 Posters(扫描线+线段树)(2009 Asia Ningbo Regional)
Description Ted has a new house with a huge window. In this big summer, Ted decides to decorate the ...
- hdu 4419 Colourful Rectangle (离散化扫描线线段树)
Problem - 4419 题意不难,红绿蓝三种颜色覆盖在平面上,不同颜色的区域相交会产生新的颜色,求每一种颜色的面积大小. 比较明显,这题要从矩形面积并的方向出发.如果做过矩形面积并的题,用线段树 ...
- HDU 1255 覆盖的面积 (扫描线 线段树 离散化 矩形面积并)
题目链接 题意:中文题意. 分析:纯手敲,与上一道题目很相似,但是刚开始我以为只是把cnt>=0改成cnt>=2就行了,. 但是后来发现当当前加入的线段的范围之前 还有线段的时候就不行了, ...
- hdu 3642 Get The Treasury(扫描线)
pid=3642" style="">题目链接:hdu 3642 Get The Treasury 题目大意:三维坐标系,给定若干的长方体,问说有多少位置被覆盖3次 ...
- hdu 3642 Get The Treasury
Get The Treasury http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Othe ...
- 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树
[BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...
- 【bzoj4491】我也不知道题目名字是什么 离线扫描线+线段树
题目描述 给定一个序列A[i],每次询问l,r,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串 输入 第一行n,表示A数组有多少元素接下来一行为n个整数A[i]接下来一个整数Q,表示询问数 ...
- hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积
题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> ...
- P3722 [AH2017/HNOI2017]影魔(单调栈+扫描线+线段树)
题面传送门 首先我们把这两个贡献翻译成人话: 区间 \([l,r]\) 产生 \(p_1\) 的贡献当且仅当 \(a_l,a_r\) 分别为区间 \([l,r]\) 的最大值和次大值. 区间 \([l ...
随机推荐
- 不用数据线连接到Android手机进行调试
这两天USB线丢了,老是找同事借也不方便,于是就网上找各种方法,这里总结个最简单的,当然你的手机需要root: 1 要打开WIFI,手机要和电脑在同一局域网内,这个你可以使用你的开发机共享wifi即可 ...
- 解决win10休眠后无法唤醒
在控制面板-电源选项-编辑计划设置-高级电源设置中把"睡眠"的选项中休眠调整为从不,"电源按键和盖子"选项中也都设为睡眠,这样使得无论你是使用电池还是电源,系统 ...
- 服务端测试之接口测试工具——postman
今天跟大家分享一个非常常见大家也非常熟悉的测试工具——postman. 1.安装postman postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件.打开chrome浏览器, ...
- Bypass 360主机卫士SQL注入防御(多姿势)
0x00 前言 在服务器客户端领域,曾经出现过一款360主机卫士,目前已停止更新和维护,官网都打不开了,但服务器中依然经常可以看到它的身影.从半年前的测试虚拟机里面,翻出了360主机卫士Apache版 ...
- PC 商城扫描二维码登录
需求分析: 扫码入口,在pc登录首页新增二维码登录入口 点击扫码入口显示二维码 二维码有效时间为一分钟 超时后显示二维码失效,点击刷新后生成新的二维码 在app端用户登录并扫码后,点击确认登录,进行跳 ...
- jQuery ajax中serialize()方法增加其他参数
表单提交 使用jQuery.ajax()进行表单提交时,需要传递参数,最直接的方法便是使用Form的serializa()将表单序列化,前提只是将Form表单中的name属性与数据库的字段名保持一致便 ...
- linux下复制文件报cp: omitting directory `XXX'
错误操作:这个错误是因为在linux下我使用cp复制一个文件夹A到另一个目录下时报错cp: omitting directory `XXX' 原因:文件夹A中还有子目录文件,所以linux不允许直接复 ...
- spring mvc 篇
[1]spring mvc 实现多文件上传 http://blog.csdn.net/a1314517love/article/details/24183273 http://bbs.csdn.net ...
- RewriteCond和13个mod_rewrite应用举例Apache伪静态
1.给子域名加www标记 RewriteCond %{HTTP_HOST} ^([a-z.]+)?example\.com$ [NC] RewriteCond %{HTTP_HOST} !^www\. ...
- Python在mysql中进行操作是十分容易和简洁的
首先声明一下,我用的是Windows系统! 1.在Python中对mysql数据库进行操作首先要导入pymysql模块,默认情况下,Python中是没有安装这个模块的, 可以在Windows的命令行中 ...