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个序列,那么每个序列都有一个逆序数,找 ...
随机推荐
- 创建 XXXXXXXX 的配置节处理程序时出错: 请求失败
今天碰到这个错误,之前的程序在测试的时候都没有问题,同样的程序打包通过QQ传给其他人,在XP下测试也没有问题,我的Win7系统从QQ信箱下载压缩包,解压之后执行程序就会出问题,本来还是考虑自己程序是不 ...
- JS中如何得到触发事件的属性?
<html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> ...
- 中期ppt制作
陀螺仪的使用解释:https://zhuanlan.zhihu.com/p/29244429 手机坐标轴的图片:http://jcjs.siat.ac.cn/ch/reader/create_pdf. ...
- mingw libgcc_s_sjlj-1.dll is missing
习惯了在linux环境下工作,编译wingdows平台程序采用mingw工具.编译完,运行exe程序,弹出错误信息: libgcc_s_sjlj-1.dll is missing 百度了一下,原来是编 ...
- JQuery基础原理 与实例 验证表单 省市联动 文本框判空 单选 复选 判空 下拉判空 确认密码判等
JQuery 基础原理 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> & ...
- HDU.2111 Saving HDU(贪心)
题目来源:Saving HDU 题意分析: XHD有个容量为v的口袋,有n个宝贝,每种宝贝的价值不一样,每种宝贝单位体积的价格也不一样,宝贝可以分割,分割后的价值和对应的体积成正比.求XHD最多能取回 ...
- Java分享笔记:FileInputStream流的 read()方法 和 read(byte[] b)方法
/*------------------------ FileInputStream: ....//输入流,字节流 ....//从硬盘中存在的一个文件中读取内容,读取到程序中 ....//read() ...
- 【杂题总汇】HDU多校赛第十场 Videos
[HDU2018多校赛第十场]Videos 最后一场比赛也结束了…… +HDU传送门+ ◇ 题目 <简要翻译> 有n个人以及m部电影,每个人都有一个快乐值.每场电影都有它的开始.结束时间和 ...
- datatable常用设置
bSort: false, // 是否排序功能 bFilter: false, // 过滤功能 bPaginate: true, // 翻页功能 bInfo: true, // 页脚信息 bProce ...
- C5509A启动使用定时器
#include <stdio.h> #include <csl.h> #include <csl_pll.h> #include <csl_chip.h&g ...