求覆盖三次及其以上的长方体体积并。

这题跟 http://wenku.baidu.com/view/d6f309eb81c758f5f61f6722.html 这里讲的长方体体积并并不一样。

因为本题Z坐标范围非常小,所以可以离散化Z坐标,枚举每个体积块。

对每一个体积块:用底面积*高求其体积。底面积直接用“线段树求长方形面积并”来得到即可。

对于覆盖次数,pushUp的时候:

1.满足 当前覆盖次数大于等于3的,直接求线段长。

2.小于3的,由 左右儿子覆盖次数=3 - 当前覆盖次数 的两个儿子更新上来得到。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm> using namespace std; #define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define lc rt << 1
#define rc rt << 1 | 1
#define LL long long int const int MAXN = ; struct cube
{
int x1, y1, z1;
int x2, y2, z2;
void readCube()
{
scanf( "%d%d%d", &x1, &y1, &z1 );
scanf( "%d%d%d", &x2, &y2, &z2 );
return;
}
}cb[MAXN]; struct Line
{
int s; //sao ru sao chu
int x;
int y1, y2;
Line() {}
Line( int s, int x, int y1, int y2 ): s(s), x(x), y1(y1), y2(y2) { }
void showLine()
{
printf("s=%d x=%d y1=%d y2=%d\n", s, x, y1, y2 );
return;
}
}; struct node
{
int cnt;
int len[];
}; int N;
node Tr[ MAXN << ];
Line L[ MAXN << ];
int Z[MAXN << ];
int Y[MAXN << ]; //li san hua
int cntZ, cntY; bool cmp( const Line& a, const Line &b )
{
if ( a.x != b.x ) return a.x < b.x;
return a.s > b.s;
} void build( int l, int r, int rt )
{
for ( int i = ; i < ; ++i )
Tr[rt].len[i] = ;
Tr[rt].cnt = ;
if ( l == r ) return;
int m = ( l + r ) >> ;
build( lson );
build( rson );
return;
} void PushUp( int rt, int l, int r )
{
//len0
if ( Tr[rt].cnt > )
Tr[rt].len[] = Y[r+] - Y[l];
else
Tr[rt].len[] = Tr[lc].len[] + Tr[rc].len[]; //len1
if ( Tr[rt].cnt > )
Tr[rt].len[] = Y[r+] - Y[l];
else if ( Tr[rt].cnt == )
Tr[rt].len[] = Tr[lc].len[] + Tr[rc].len[];
else
Tr[rt].len[] = Tr[lc].len[] + Tr[rc].len[]; //len2
if ( Tr[rt].cnt > )
Tr[rt].len[] = Y[r+] - Y[l];
else if ( Tr[rt].cnt == )
Tr[rt].len[] = Tr[lc].len[] + Tr[rc].len[];
else if ( Tr[rt].cnt == )
Tr[rt].len[] = Tr[lc].len[] + Tr[rc].len[];
else
Tr[rt].len[] = Tr[lc].len[] + Tr[rc].len[]; return;
} void Update( int L, int R, int v, int l, int r, int rt )
{
if ( L <= l && r <= R )
{
Tr[rt].cnt += v;
PushUp( rt, l, r );
return;
}
if ( l == r ) return; int m = ( l + r ) >> ; if ( L <= m ) Update( L, R, v, lson );
if ( R > m ) Update( L, R, v, rson ); PushUp( rt, l, r );
return;
} int main()
{
int T, cas = ;
scanf( "%d", &T );
while ( T-- )
{
scanf( "%d", &N );
cntZ = ;
cntY = ;
for ( int i = ; i < N; ++i )
{
cb[i].readCube();
Z[cntZ++] = cb[i].z1;
Z[cntZ++] = cb[i].z2;
Y[cntY++] = cb[i].y1;
Y[cntY++] = cb[i].y2;
} sort( Z, Z + cntZ );
sort( Y, Y + cntY );
cntZ = unique( Z, Z + cntZ ) - Z;
cntY = unique( Y, Y + cntY ) - Y; LL ans = ;
for ( int i = ; i < cntZ - ; ++i )
{
int cntL = ;
for ( int j = ; j < N; ++j )
{
if ( cb[j].z1 <= Z[i] && cb[j].z2 >= Z[i + ] )
{
L[cntL++] = Line( , cb[j].x1, cb[j].y1, cb[j].y2 );
L[cntL++] = Line(-, cb[j].x2, cb[j].y1, cb[j].y2 );
}
} sort( L, L + cntL, cmp );
build( , cntY - , ); for ( int k = ; k < cntL; ++k )
{
if ( k )
ans += (LL)( L[k].x-L[k-].x )*Tr[].len[]*( Z[i+]-Z[i] );
int a = lower_bound( Y, Y + cntY, L[k].y1 ) - Y;
int b = lower_bound( Y, Y + cntY, L[k].y2 ) - Y - ; //这里一定要减1!!!!!!
Update( a, b, L[k].s, , cntY - , );
}
} printf( "Case %d: %lld\n", ++cas, ans );
}
return ;
}

之前一直调试不出结果,是因为点树和线段树没分清楚,就是线段树节点中存的是一个点,还是一个单位长度倍数的线段。

对于二分得到a,b值,b值需要-1,而pushUp的时候r值需要+1这里并不是很理解。

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://blog.csdn.net/zxy_snow/article/details/6870127 题意:给你n个立方体,求覆盖三次以上(包括三次)的区域的体积 思路:先将z坐标 ...

  3. hdu 1754 I Hate It (线段树求区间最值)

    HDU1754 I Hate It Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u D ...

  4. HDU 1828 / POJ 1177 Picture --线段树求矩形周长并

    题意:给n个矩形,求矩形周长并 解法:跟求矩形面积并差不多,不过线段树节点记录的为: len: 此区间线段长度 cover: 此区间是否被整个覆盖 lmark,rmark: 此区间左右端点是否被覆盖 ...

  5. HDU 1264 Counting Squares(线段树求面积的并)

    Counting Squares Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  6. [HDU] 1394 Minimum Inversion Number [线段树求逆序数]

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...

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

    链接:线段树求矩形面积并 扫描线+离散化 1.给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 2.看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同. 求面积时,用被覆 ...

  8. HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)

    HDU 1394 Minimum Inversion Number(线段树求最小逆序数对) ACM 题目地址:HDU 1394 Minimum Inversion Number 题意:  给一个序列由 ...

  9. hdu 1394 (线段树求逆序数)

    <题目链接> 题意描述: 给你一个有0--n-1数字组成的序列,然后进行这样的操作,每次将最前面一个元素放到最后面去会得到一个序列,那么这样就形成了n个序列,那么每个序列都有一个逆序数,找 ...

随机推荐

  1. json 序列化和反序列化的3个方法

    https://www.cnblogs.com/caofangsheng/p/5687994.html

  2. MAC下查看环境变量的值的方法

    方法很简单,用到的命令是:echo. env : 查看所有的环境变量 方法:启动终端->输入 echo + 环境变量名, 回车,即可看到边聊的值. 例如:echo $JAVA_HOME

  3. P1024 一元三次方程求解

    P1024 一元三次方程求解 #include<cstdio> #include<iostream> #include<algorithm> using names ...

  4. 统计函数运行时间-CPU端

    C/C++中的计时函数是clock(),而与其相关的数据类型是clock_t.在MSDN中,查得对clock函数定义如下:  clock_t clock( void ); 这个函数返回从“开启这个程序 ...

  5. 开发常用宏 - iOS

    以下是一些开发中会经常用到的宏,简单的进行了整理,为了今后可以更加方便的使用,从而提升开发的效率,不为此搭进去更多时间. 也希望有大家可以补充,从而使其更加强加! /** * 开发常用宏相关 */ # ...

  6. MBProgressHUD 优雅地去提示

    项目主页: MBProgressHUD 实例下载: 点击下载 快速上手: 当执行需要较长时间的任务时,使用MBProgressHUD最重要的一点是: 保证主线程是空闲的,这样可以使UI实时更新.因此: ...

  7. ARC下需要注意的内存问题

    之前发了一篇关于图片加载优化的文章,还是引起很多人关注的,不过也有好多人反馈看不太懂,这次谈谈iOS中ARC的一些使用注意事项,相信做iOS开发的不会对ARC陌生啦.这里不是谈ARC的使用,只是介绍下 ...

  8. ES6初识-模块化

    export let A=123; export function test(){ console.log('test'); } export class Hello(){ test(){ conso ...

  9. 转:mysql远程连接 Host * is not allowed to connect to this MySQL server

    在本机登入mysql后,更改"mysql"数据库里的"user"表里的"host"项,从"localhost"改为'%' ...

  10. Ansible学习 Playbooks_1

    Playbooks是Ansible中执行较复杂任务的一种的方式,Playbook由1个或多个play组成,语法格式是YAML,下面以一个简单的任务为例,开始我们的Playbook学习: 任务描述: 1 ...