HDU 3642 Get The Treasury(离散化+线段树:扫描线)
来源:互联网 发布:mac图标放在桌面 编辑:程序博客网 时间:2024/06/14 08:49
HDU 3642 Get The Treasury(离散化+线段树:扫描线)
http://acm.hdu.edu.cn/showproblem.php?pid=3642
分析:
本题要求的是重叠3次及以上的立方体体积,由于Z轴范围很小,可以枚举Z轴,然后固定了Z轴之后,就是求二维矩形的面积交>=3次的总面积了.其实Z轴就算很大也可以求,只需要把Z轴离散化即可.
比如Z轴从小到大出现了1,10,100,1000共四个值.然后假设当前考虑Z==1时,那么只需要把那些包括了[1,10]区间的立方体加入到二维矩形球面积的线段树扫描线中即可.如何判断一个立方体包括了区间[1,10]呢? 只要该立方体的Z轴最小值<=1且Z轴最大值>1,那么它就必然包括了区间[1,10].想想是不是.
对于每个给定的Z轴区间,我们只要求出交>=3次以上的总面积res,然后用res*该Z轴区间长度,即可求出该区间的ans体积.由于X轴的范围也很大,所以X轴也需要离散化处理.
线段树需要维护的信息有:
cover:值为0,1,2,3,4… 表示当前节点控制的X轴区被覆盖的次数.
sum: 表示当前节点控制的X轴区域被覆盖次数>=3的总长度
len1: 表示当前节点控制的X轴区域被覆盖次数=1的总长度
len2: 示当前节点控制的X轴区域被覆盖次数=2的总长度
具体实现见代码.
AC代码:1468ms
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN=2222;#define lson i*2,l,m#define rson i*2+1,m+1,rint cover[MAXN*4],sum[MAXN*4],len1[MAXN*4],len2[MAXN*4];int X[MAXN],Z[MAXN];int cnt_x,cnt_z;struct seg{ int l,r,h,d; seg(){} seg(int a,int b,int c,int d):l(a),r(b),h(c),d(d){} bool operator < (const seg& b)const { return h<b.h; }}ss[MAXN];struct point{ int x,y,z; void read() { scanf("%d%d%d",&x,&y,&z); }};struct cube{ point a,b;}cubes[MAXN];void PushUp(int i,int l,int r){ if(cover[i]>=3) { sum[i]=X[r+1]-X[l]; len1[i]=len2[i]=0; } else if(cover[i]==2) { sum[i]=sum[i*2]+sum[i*2+1]+len1[i*2]+len1[i*2+1]+len2[i*2]+len2[i*2+1]; len2[i]=X[r+1]-X[l]-sum[i]; len1[i]=0; } else if(cover[i]==1) { sum[i]=sum[i*2]+sum[i*2+1]+len2[i*2]+len2[i*2+1]; len2[i]=len1[i*2]+len1[i*2+1]; len1[i]=X[r+1]-X[l]-sum[i]-len2[i]; } else { sum[i]=sum[i*2]+sum[i*2+1]; len1[i]=len1[i*2]+len1[i*2+1]; len2[i]=len2[i*2]+len2[i*2+1]; }}void update(int ql,int qr,int v,int i,int l,int r){ if(ql<=l&&r<=qr) { cover[i]+=v; PushUp(i,l,r); return ; } int m=(l+r)>>1; if(ql<=m) update(ql,qr,v,lson); if(m<qr) update(ql,qr,v,rson); PushUp(i,l,r);}int main(){ int T; scanf("%d",&T); for(int kase=1;kase<=T;kase++) { int n; cnt_x=cnt_z=0; scanf("%d",&n); for(int i=1;i<=n;i++) { cubes[i].a.read(); cubes[i].b.read(); X[cnt_x++]=cubes[i].a.x; X[cnt_x++]=cubes[i].b.x; Z[cnt_z++]=cubes[i].a.z; Z[cnt_z++]=cubes[i].b.z; } if(n<3) { printf("Case %d: 0\n",kase); continue; } sort(X,X+cnt_x); sort(Z,Z+cnt_z); cnt_x=unique(X,X+cnt_x)-X; cnt_z=unique(Z,Z+cnt_z)-Z; long long ans=0; for(int i=0;i<cnt_z-1;i++) { int cnt=0; long long res=0; for(int j=1;j<=n;j++) { if(cubes[j].a.z<=Z[i] && cubes[j].b.z>Z[i]) { ss[cnt++]=seg(cubes[j].a.x,cubes[j].b.x,cubes[j].a.y,1); ss[cnt++]=seg(cubes[j].a.x,cubes[j].b.x,cubes[j].b.y,-1); } } sort(ss,ss+cnt); memset(cover,0,sizeof(cover)); memset(sum,0,sizeof(sum)); memset(len1,0,sizeof(len1)); memset(len2,0,sizeof(len2)); for(int j=0;j<cnt-1;j++) { int ql=lower_bound(X,X+cnt_x,ss[j].l)-X; int qr=lower_bound(X,X+cnt_x,ss[j].r)-X-1; update(ql,qr,ss[j].d,1,0,cnt_x-1); res +=(long long)sum[1]*(ss[j+1].h-ss[j].h); } ans += res*(Z[i+1]-Z[i]); } printf("Case %d: %I64d\n",kase,ans); }}
0 0
- HDU 3642 Get The Treasury(离散化+线段树:扫描线)
- HDU 3642 Get The Treasury[离散化 + 扫描线 + 线段树]
- HDU 3642——Get The Treasury(线段树+扫描线+离散化+体积交多次)
- HDU 3642 Get The Treasury 【线段树】【扫描线】
- hdu3642-Get The Treasury 线段树+扫描线+离散化 求三维体积并
- hdu 3642 Get The Treasury(扫描线)
- HDU 3642 Get The Treasury (线段树、扫描线求立方体体积交)
- HDU 3642 Get The Treasury(体积并+覆盖三次+线段树+扫描线)
- HDU 3642 Get The Treasury(体积并,离散化)
- HDU 3642 Get The Treasury (线段树扫描线进阶--求长方体重叠3次或以上的体积)
- HDU 3642 Get The Treasury(线段树+扫描线求面积【再升级版(三维)】)
- hdu 3642 Get The Treasury (三维的扫描线)
- hdu 3642 Get The Treasury(扫描线、立方体交)
- hdoj 3642 Get The Treasury 【线段树 扫描线 求立方体积交】
- hdu 3642 Get The Treasury(线段树求体积并)
- hdu-3642--Get The Treasury-线段树求面积并
- HDU 3642 Get The Treasury(线段树)
- hdu3642 Get The Treasury--线段树 & 扫描线 & 面积并(待解决)
- mac os 安装 boost库
- CF 407A Triangle
- PHP基础教程之正则表达式
- 深入理解JavaScript系列(3):全面解析Module模式
- 004_015 Python 字典的一键多值,即一个键对应多个值
- HDU 3642 Get The Treasury(离散化+线段树:扫描线)
- 我的C++第四周作业2(第三章作业2-10)
- 其实自己胆量真的还不够
- hibernate 4.x buildSessionFactory 的使用
- 深入理解JavaScript系列(4):立即调用的函数表达式
- C语言中scanf、getchar、gets函数的比较
- 关于*p++ *(p++) (*p)++ *++p *(++p) ++*p ++(*p)
- Extjs4.0.7 提交表单
- 如何理解指向指针的指针?