HDU 3642 Get The Treasury ( 线段树 求长方体体积并 )
求覆盖三次及其以上的长方体体积并。
这题跟 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 ( 线段树 求长方体体积并 )的更多相关文章
- HDU 3642 Get The Treasury 线段树+分层扫描线
http://www.acmerblog.com/hdu-3642-get-the-treasury-6603.html 学习:三维就是把竖坐标离散化分层,每一层进行线段树二维面积并就好了
- HDU 3642 Get The Treasury (线段树扫描线,求体积并)
参考链接 : http://blog.csdn.net/zxy_snow/article/details/6870127 题意:给你n个立方体,求覆盖三次以上(包括三次)的区域的体积 思路:先将z坐标 ...
- hdu 1754 I Hate It (线段树求区间最值)
HDU1754 I Hate It Time Limit:3000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u D ...
- HDU 1828 / POJ 1177 Picture --线段树求矩形周长并
题意:给n个矩形,求矩形周长并 解法:跟求矩形面积并差不多,不过线段树节点记录的为: len: 此区间线段长度 cover: 此区间是否被整个覆盖 lmark,rmark: 此区间左右端点是否被覆盖 ...
- HDU 1264 Counting Squares(线段树求面积的并)
Counting Squares Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- [HDU] 1394 Minimum Inversion Number [线段树求逆序数]
Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java ...
- HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)
链接:线段树求矩形面积并 扫描线+离散化 1.给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 2.看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同. 求面积时,用被覆 ...
- HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)
HDU 1394 Minimum Inversion Number(线段树求最小逆序数对) ACM 题目地址:HDU 1394 Minimum Inversion Number 题意: 给一个序列由 ...
- hdu 1394 (线段树求逆序数)
<题目链接> 题意描述: 给你一个有0--n-1数字组成的序列,然后进行这样的操作,每次将最前面一个元素放到最后面去会得到一个序列,那么这样就形成了n个序列,那么每个序列都有一个逆序数,找 ...
随机推荐
- 剑指offer54 表示数值的字符串
错误的代码: class Solution { public: bool isNumeric(char* string) { if(string == NULL) return false; if(* ...
- 自己编写shave函数
import numpy def shave(I,border=None): I = I[border[0]:I.shape[0]-border[0],border[1]:I.shape[1]-bor ...
- CSS中margin: 0 auto;样式没有生效
问题:有两个元素: A, B.两则是嵌套关系,A是B的父节点.A和B都是块元素.当在A上设置:margin: 0 auto的时候,B并没有在页面中居中. margin: 0 auto 为什么没有生效? ...
- node.js启动调试方式
node.js启动调试方式(nodeJs不能像js一样在控制台调试) 以express项目为例,启动路径是localhost:3000 一.通过node命令启动 node server/bin/www ...
- c/c++面试指导---c语言基础算法总结1
c语言基础算法总结 1 初学者学习任何一门编程语言都必须要明确,重点是学习编程方法和编程思路,不是学习语法规则,语法规则是为编程实现提供服务和支持.所以只要认真的掌握了c语言编程方法,在学习其它的语 ...
- LVS基于NAT模式搭建负载均衡群集
LVS的基本架构图 负载均衡群集中,包括三个层次的组件: 1.第一层,负载调度器(BL) 前段至少有一个负载调度器(Load Balancer 或称为Director)负责响应并分发来自客户端的访问请 ...
- 简单了解,使用oracle中的索引,表分区
索引的分类 如下: 物理分类 逻辑分类 分区或非分区索引 单列或组合索引 B树索引(标准索引) 唯一或非唯一索引 正常或反向键索引 基于函数索引 位图索引 B树索引 b树索引通常也称为标准索引,索 ...
- form表单submit按钮提交页面不跳转
方案一 <html> <body> <form action="" method="post" target="nm_i ...
- web前端工程师面试技巧 常见问题解答
web前端工程师面试技巧 常见问题解答 每年的春招是各企业需求人才的黄金时期,不少的前端大牛或者前端新手在面试时候不知道怎么来回答面试官的问题,下面来看下我转载的这篇文章吧,希望对从事前端工作的你有所 ...
- python的多继承C3(mro)算法
多继承的继承顺序按照C3算法进行顺序继承 例一 按照深度A类从左往右有三条可继承的"路" 先按照深度优先的算法,将每一路的每一个节点加到列表中 B = [B,D,F,H] C = ...