参考链接 : http://blog.csdn.net/zxy_snow/article/details/6870127

题意:给你n个立方体,求覆盖三次以上(包括三次)的区域的体积

思路:先将z坐标离散后,然后一层一层地开始扫描,计算该层中覆盖>=3次的面积,这个就同二维扫描一样,然后再用面积乘以这层的高度,
    即得到该层覆盖>=3次的体积,所有层的体积加起来,即为所求。
    对于每一层,只有当该层区域在扫描的线的z1,z2范围中,才将该线条插入。
    其它操作就同POJ 1151 Atlantis 求矩形的面积并一样。

    这里要注意的是,如果扫描的时候,是用单点更新,那么就会TLE。
    后来看了网上别人的区间更新的代码,这才A了。

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#define lson rt<<1,L,mid
#define rson rt<<1|1,mid,R
/*
AC
参考链接
http://blog.csdn.net/zxy_snow/article/details/6870127 题意:给你n个立方体,求覆盖三次以上(包括三次)的区域的体积 思路:先将z坐标离散后,然后一层一层地开始扫描,计算该层中覆盖>=3次的面积,这个就同二维扫描一样,然后再用面积乘以这层的高度,
即得到该层覆盖>=3次的体积,所有层的体积加起来,即为所求。
对于每一层,只有当该层区域在扫描的线的z1,z2范围中,才将该线条插入。
其它操作就同POJ 1151 Atlantis 求矩形的面积并一样。 这里要注意的是,如果扫描的时候,是用单点更新,那么就会TLE。
后来看了网上别人的区间更新代码,这才A了。
*/
using namespace std;
const int maxn=;
int n;
int xval[maxn*],zval[maxn*]; //存储x和z出现的所有值
int idx,idz; //xval和zval存储的数的个数
int hashx[maxn*],hashz[maxn*]; //用于离散化
int hx,hz; //x和z离散后的个数
long long ans; struct Line{
//l r:线条的横坐标左端点和右端点;y:纵坐标值
//z1 z2:线条所处的z坐标范围
int l,r,y,z1,z2;
int tp; //标记,tp=1表示矩形的下边,tp=-1表示矩形的上边
bool operator<(const Line tmp)const{
return y<tmp.y;
}
}line[maxn*]; struct Node{
int cnt; //该区间被覆盖的次数
/*
once:该区间中被覆盖一次的线段长度
twice:该区间中被覆盖两次的线段长度
len:该区间中被覆盖>=三次的线段长度
*/
long long once,twice,len;
}tree[maxn<<]; //二分搜索x坐标对应的离散值
int binarySearchx(int m){
int l=,r=hx+,mid;
while(r-l>){
mid=(l+r)>>;
if(hashx[mid]<=m)
l=mid;
else
r=mid;
}
return l;
} void build(int rt,int L,int R){
tree[rt].cnt=tree[rt].len=tree[rt].twice=tree[rt].once=;
if(L+==R)
return;
int mid=(L+R)>>;
build(lson);
build(rson);
}
/*
还是网上看了大牛们的代码,用区间查询,才AC
原本自己就直接单点更新,导致TLE。。。
*/
void pushUp(int rt,int L,int R){
if(tree[rt].cnt>=){
tree[rt].once=tree[rt].twice=;
tree[rt].len=hashx[R]-hashx[L];
}
else if(tree[rt].cnt==){
if(L+==R){
tree[rt].once=tree[rt].len=;
tree[rt].twice=hashx[R]-hashx[L];
}
else{
tree[rt].once=;
tree[rt].len=tree[rt<<].len+tree[rt<<|].len+tree[rt<<].twice+tree[rt<<|].twice
+tree[rt<<].once+tree[rt<<|].once;
tree[rt].twice=hashx[R]-hashx[L]-tree[rt].len;
}
}
else if(tree[rt].cnt==){
if(L+==R){
tree[rt].once=hashx[R]-hashx[L];
tree[rt].twice=tree[rt].len=;
}
else{
tree[rt].len=tree[rt<<].len+tree[rt<<|].len+tree[rt<<].twice+tree[rt<<|].twice;
tree[rt].twice=tree[rt<<].once+tree[rt<<|].once;
tree[rt].once=hashx[R]-hashx[L]-tree[rt].len-tree[rt].twice;
}
}
else{
if(L+==R){
tree[rt].len=tree[rt].once=tree[rt].twice=;
}
else{
tree[rt].len=tree[rt<<].len+tree[rt<<|].len;
tree[rt].twice=tree[rt<<].twice+tree[rt<<|].twice;
tree[rt].once=tree[rt<<].once+tree[rt<<|].once;
}
}
} void update(int rt,int L,int R,int l,int r,int c){
if(l<=L&&R<=r){
tree[rt].cnt+=c;
pushUp(rt,L,R);
return;
}
int mid=(L+R)>>;
if(r<=mid)
update(lson,l,r,c);
else if(l>=mid)
update(rson,l,r,c);
else{
update(lson,l,mid,c);
update(rson,mid,r,c);
}
pushUp(rt,L,R);
}
int main()
{
int t;
int x1,y1,z1,x2,y2,z2;
scanf("%d",&t);
for(int q=;q<=t;q++){
scanf("%d",&n);
idx=idz=;
for(int i=;i<=n;i++){
scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
line[*i-].l=x1;line[*i-].r=x2;line[*i-].y=y1;line[*i-].z1=z1;line[*i-].z2=z2;line[*i-].tp=;
line[*i].l=x1;line[*i].r=x2;line[*i].y=y2;line[*i].z1=z1;line[*i].z2=z2;line[*i].tp=-;
xval[++idx]=x1;
xval[++idx]=x2;
zval[++idz]=z1;
zval[++idz]=z2;
}
n=n*;
sort(line+,line+n+);
sort(xval+,xval+idx+);
sort(zval+,zval+idz+);
hx=hz=;
//将x坐标值离散化
hashx[++hx]=xval[];
for(int i=;i<=idx;i++){
if(xval[i]!=xval[i-])
hashx[++hx]=xval[i];
}
//将y坐标值离散化
hashz[++hz]=zval[];
for(int i=;i<=idz;i++){
if(zval[i]!=zval[i-])
hashz[++hz]=zval[i];
} ans=;
int minz,maxz;
int a,b;
//一层一层地扫描
for(int i=;i<hz;i++){
//minz和maxz表示该层所处的范围
minz=hashz[i];
maxz=hashz[i+];
build(,,hx);
long long s=; //该层被覆盖>=3的面积
int last=; //记录上一次扫描线的编号
for(int j=;j<=n;j++){
if(line[j].z1<=minz && maxz<=line[j].z2){
s+=tree[].len*(line[j].y-line[last].y);
last=j;
a=binarySearchx(line[j].l);
b=binarySearchx(line[j].r);
update(,,hx,a,b,line[j].tp);
}
}
ans+=s*(maxz-minz);
}
printf("Case %d: %I64d\n",q,ans);
}
return ;
}

后来这道题自己又做了一遍,基本上和之前的差不多,只不过离散化的时候就在原来数组的基础上进行

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define lson rt<<1,L,mid
#define rson rt<<1|1,mid+1,R
using namespace std;
const int maxn=+;
int n,m;
int cntx,idx;
int cntz,idz;
int hashx[maxn<<];
int hashz[maxn<<]; struct Line{
int y,l,r;
int tp;
int z1,z2;
bool operator<(const Line tmp)const{
return y<tmp.y;
}
}line[maxn<<]; struct Node{
int cnt;
int len[];
}tree[maxn<<]; void build(int rt,int L,int R){
tree[rt].cnt=;
tree[rt].len[]=tree[rt].len[]=tree[rt].len[]=;
if(L==R)
return;
int mid=(L+R)>>;
build(lson);
build(rson);
} void pushUp(int rt,int L,int R){
//别忘了考虑叶子节点的情况
if(tree[rt].cnt==){
if(L==R){
tree[rt].len[]=tree[rt].len[]=tree[rt].len[]=;
}
else{
tree[rt].len[]=tree[rt<<].len[]+tree[rt<<|].len[];
tree[rt].len[]=tree[rt<<].len[]+tree[rt<<|].len[];
tree[rt].len[]=tree[rt<<].len[]+tree[rt<<|].len[];
}
}
else if(tree[rt].cnt==){
if(L==R){
tree[rt].len[]=hashx[R+]-hashx[L];
tree[rt].len[]=tree[rt].len[]=;
}
else{
tree[rt].len[]=tree[rt<<].len[]+tree[rt<<|].len[]+tree[rt<<].len[]+tree[rt<<|].len[];
tree[rt].len[]=tree[rt<<].len[]+tree[rt<<|].len[];
tree[rt].len[]=hashx[R+]-hashx[L]-tree[rt].len[]-tree[rt].len[];
}
}
else if(tree[rt].cnt==){
if(L==R){
tree[rt].len[]=hashx[R+]-hashx[L];
tree[rt].len[]=tree[rt].len[]=;
}
else{
tree[rt].len[]=;
tree[rt].len[]=tree[rt<<].len[]+tree[rt<<].len[]+tree[rt<<].len[]
+tree[rt<<|].len[]+tree[rt<<|].len[]+tree[rt<<|].len[];
tree[rt].len[]=hashx[R+]-hashx[L]-tree[rt].len[];
}
}
else{
tree[rt].len[]=tree[rt].len[]=;
tree[rt].len[]=hashx[R+]-hashx[L];
}
}
void update(int rt,int L,int R,int l,int r,int val){
if(l<=L&&R<=r){
tree[rt].cnt+=val;
pushUp(rt,L,R);
return;
}
int mid=(L+R)>>;
if(l<=mid)
update(lson,l,r,val);
if(r>mid)
update(rson,l,r,val);
pushUp(rt,L,R);
}
int binarySearch(int x){
int l=,r=idx+,mid;
while(r-l>){
mid=(l+r)>>;
if(hashx[mid]<=x)
l=mid;
else
r=mid;
}
return l;
}
int main()
{
int t;
int x1,y1,z1,x2,y2,z2;
scanf("%d",&t);
for(int q=;q<=t;q++){
scanf("%d",&n);
cntx=cntz=;
for(int i=;i<=n;i++){
scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
line[*i-].y=y1;line[*i-].l=x1;line[*i-].r=x2;
line[*i-].z1=z1;line[*i-].z2=z2;line[*i-].tp=;
line[*i].y=y2;line[*i].l=x1;line[*i].r=x2;
line[*i].z1=z1;line[*i].z2=z2;line[*i].tp=-;
hashx[cntx++]=x1;
hashx[cntx++]=x2;
hashz[cntz++]=z1;
hashz[cntz++]=z2;
}
n=n*;
sort(hashx+,hashx+cntx);
sort(hashz+,hashz+cntz);
idx=;
for(int i=;i<cntx;i++){
if(hashx[i]!=hashx[i-]){
hashx[++idx]=hashx[i];
}
}
idz=;
for(int i=;i<cntz;i++){
if(hashz[i]!=hashz[i-])
hashz[++idz]=hashz[i];
}
sort(line+,line+n+); long long ans=;
for(int i=;i<idz;i++){
long long area=;
int last=;
build(,,idx);
for(int j=;j<=n;j++){
if(line[j].z1<=hashz[i] && hashz[i+]<=line[j].z2){
//这里乘积可能会爆int,所以要转化成long long,或者将tree[1].len定义成long long
area+=(long long)tree[].len[]*(line[j].y-line[last].y);
int a=binarySearch(line[j].l);
int b=binarySearch(line[j].r)-;
update(,,idx,a,b,line[j].tp);
last=j;
}
}
ans+=area*(hashz[i+]-hashz[i]);
}
printf("Case %d: %I64d\n",q,ans);
}
return ;
}

HDU 3642 Get The Treasury (线段树扫描线,求体积并)的更多相关文章

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

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

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

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

  3. hdu3642 Get The Treasury 线段树--扫描线

    Jack knows that there is a great underground treasury in a secret region. And he has a special devic ...

  4. HDU 1264 Counting Squares (线段树-扫描线-矩形面积并)

    版权声明:欢迎关注我的博客.本文为博主[炒饭君]原创文章,未经博主同意不得转载 https://blog.csdn.net/a1061747415/article/details/25471349 P ...

  5. HDU 4419 Colourful Rectangle --离散化+线段树扫描线

    题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何 ...

  6. hdu3255 线段树扫描线求体积

    题意:       给你n个矩形,每个矩形上都有一个权值(该矩形单位面积的价值),矩形之间可能重叠,重叠部分的权值按照最大的算,最后问这n个矩形组成的图形的最大价值. 思路:       线段树扫描线 ...

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

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 题意很清楚,就是让你求矩阵之间叠加层数大于1的矩形块的面积和. 因为n只有1000,所以我离散化 ...

  8. HDU 4419 Colourful Rectangle(线段树+扫描线)

    题目链接 主要是pushup的代码,其他和区间更新+扫描线差不多. 那个区间如果要再刷一层x,那么sum[x][rt] = que[r+1] - que[l];但是如果原本有颜色为i,颜色将会变成i| ...

  9. hdu 3642 Get The Treasury (三维的扫描线)

    题目大意: 给出N个立方体. 求一个三维空间中被包围三次的空间的体积之和. 思路分析: 发现Z的范围非常小.那么我们能够枚举Z轴,然后对 x y做扫描线. 并且不用枚举全部的Z ,仅仅须要将Z离散化之 ...

随机推荐

  1. [笔记]--Sublime Text 2使用技巧

    Sublime个人喜好设置: 在打开个人设置页面Preferences >> Settings - User,加入以下内容: { , //TAB键,4个空格 "translate ...

  2. WPF实现3D翻转的动画效果

    1.前端代码实现 1.1 原理见代码注析 <Grid MouseDown="Grid_MouseDown"> <Viewport3D> <Viewpo ...

  3. Linux基础 30分钟GDB调试快速突破

    引言 Linus心灵鸡汤 在*nix开发中有道卡叫gdb调试,不管你怎么搞. 它依然在那丝毫不会松动.今天致敬一个 活着的传奇 Linus Torvalds Unix 始于上个世纪60年代,在70年代 ...

  4. jquery easyui datebox单击文本框显示日期选择

    jquery easyui的datebox日历控件,实现单击文本框出现日历选择,如下图: 代码: 修改jquery.easyui.min.js第9797行函数(jQuery EasyUI 1.3.2) ...

  5. jdk 1.5

    1995.5.23 java语言诞生 sun公司推出java语言的同时,也推出了一系列的开发工具,比如JDK(java development Kit)JVMjava API 时间 版本 API 用途 ...

  6. Windows Phone中In-App Purchase应用内购买

    前言       应用内购买(In-App Purchase)对于开发者来说绝对是一个非常重要的功能,它提供了一个便捷的入口供用户来购买付费.在IAP盛行之前的游戏运营商一般都是通过接入第三方支付入口 ...

  7. iOS-系统自带navigationController-最全设置

    // 导航栏背景色 self.navigationController.navigationBar.barTintColor = [UIColor orangeColor]; // 设置push出来的 ...

  8. Reverse String

    Write a function that takes a string as input and returns the string reversed. Example:Given s = &qu ...

  9. easyui 布局自适应

    最近在把以前写的一个项目改成用easyui做前端.过程中遇到了不少问题.其中一个就是datagrid不能很好的布局.想了好多办法都有局限.最后想到会不会是布局(easyui-layout)的问题,经过 ...

  10. scrapy 错误

    1. 安装win32时候 Unable to find vcvarsall.bat 解决方法: 1.如果你没有安装vc,去微软下个 VS2008 的免费版就能解决此问题. 2.如果你安装的是VS201 ...