hdu3642(三维转二维扫描线)
来源:互联网 发布:c语言输出人名心形图案 编辑:程序博客网 时间:2024/06/06 16:38
比较有意思的一题,刚开始做这题的时候想到的low方法是扫描面,但这种肯定不对。。。想了一段时间,突然发现。。。枚举每个z点,就可以转化为二维上的问题。
这题还有一点需要注意,不能简单的枚举每个z点,算每个面上的重叠面积,这点是错的,具体操作请看代码
#include<iostream>#include<stdio.h>#include<cstring>#include<algorithm>#define MAX 1200using namespace std;typedef struct{ int x,y1,y2,z1,z2,f; void set(int xx,int yy1,int yy2,int zz1,int zz2,int ff) { x=xx; y1=yy1; y2=yy2; z1=zz1; z2=zz2; f=ff; }}Line;Line line[2*MAX];Line temp[MAX*2];bool cmp(const Line &a,const Line &b){ return a.x<b.x;}int y[2*MAX],z[2*MAX];typedef struct{ int left,right,realleft,realright; int one,two,three,cover; void set(int l,int r) { left=l; right=r; realleft=y[l]; realright=y[r]; three=two=one=cover=0; }}P;P p[MAX<<2];void build(int k,int l,int r){ p[k].set(l,r); if(r-l==1) return; int mid=(r+l)>>1; build(k<<1,l,mid); build(k<<1|1,mid,r);}void push_up(int k){ if( p[k].cover>2) { p[k].three= p[k].realright- p[k].realleft; p[k].two= p[k].one=0; } if( p[k].cover==2) { p[k].one=0; if( p[k].right- p[k].left==1) { p[k].three=0; p[k].two= p[k].realright- p[k].realleft; } else { int lt=k<<1,rt=lt+1; p[k].three = p[lt].one+ p[lt].two+ p[lt].three+ p[rt].one+ p[rt].two+ p[rt].three; p[k].two= p[k].realright- p[k].realleft -p[k].three; } } if( p[k].cover==1) { if( p[k].right- p[k].left==1) { p[k].three= p[k].two=0; p[k].one= p[k].realright- p[k].realleft; } else { int lt=k<<1,rt=lt+1; p[k].two= p[lt].one+ p[rt].one; p[k].three= p[lt].two+ p[rt].two+ p[lt].three+ p[rt].three; p[k].one= p[k].realright- p[k].realleft -p[k].two- p[k].three; } } if( p[k].cover==0) { if( p[k].right- p[k].left==1) { p[k].one= p[k].two= p[k].three=0; } else { int lt=k<<1,rt=lt+1; p[k].one= p[lt].one+ p[rt].one; p[k].two= p[lt].two+ p[rt].two; p[k].three= p[lt].three+ p[rt].three; } }}void update(int k,Line a){ if(a.y1==p[k].realleft&& a.y2==p[k].realright) { p[k].cover+=a.f; push_up(k); return; } if( p[k<<1].realright>= a.y2) update(k<<1,a); else if( p[k<<1|1].realleft<=a.y1) update(k<<1|1,a); else { Line m=a; m.y2= p[k<<1].realright; update(k<<1,m); m=a; m.y1= p[k<<1|1].realleft; update(k<<1|1,m); } push_up(k);}int main(){ long long sum,avg; int t,x1,x2,y1,y2,z1,z2,num=0; scanf("%d",&t); while(t--) { num++; avg=0; int n,t=0,t1=0; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2); line[t++].set(x1,y1,y2,z1,z2,1); line[t++].set(x2,y1,y2,z1,z2,-1); y[t1]=y1; z[t1++]=z1; y[t1]=y2; z[t1++]=z2; } sort(line,line+t,cmp); sort(y,y+t1); sort(z,z+t1); int len1=unique(y,y+t1)-y; int len2=unique(z,z+t1)-z; build(1,0,len1-1); for(int i=0;i<len2-1;i++) { sum=0; int m=0; for(int j=0;j<t;j++) if( line[j].z1<=z[i]&& line[j].z2>z[i]) temp[m++]=line[j]; if(m==0) continue; update(1,temp[0]); for(int j=1;j<m;j++) {//cout<<p[1].three<<endl; sum+=(long long) p[1].three*(temp[j].x- temp[j-1].x); update(1,temp[j]); } avg+=sum*(z[i+1]-z[i]);//cout<<avg<<endl; } cout<<"Case "<<num<<": "<<avg<<endl; }}
0 0
- hdu3642(三维转二维扫描线)
- hdu3642-Get The Treasury 线段树+扫描线+离散化 求三维体积并
- 线段树扫描线(体积并)hdu3642
- 三维扫描线
- 三维转二维数组
- hdu3642 Get The Treasury--线段树 & 扫描线 & 面积并(待解决)
- 【hdu3642】Get The Treasury (立方体体积交+线段树+扫描线)
- 扫描线 n个立方体相交区域大于等于三次的体积和 hdu3642 Get The Treasury
- 【SuperMap .Net 组件】二维线转三维线
- PHP 二维/三维数组转字符串
- PHP二维/三维数组转字符串
- 【基础建模】二维转三维学习笔记
- php三维数组转二维数组
- Opengl二维坐标转三维坐标
- CAD三维多线段转二维
- php三维数组转二维数组
- 【染色】三维扫描
- 【搜索】三维扫描
- 远程服务器部署javaweb项目
- 每天一个linux命令(11):ping命令
- 给出一个奇数幻方的解
- JSP中九大内置对象作用域
- Java多线程--安全问题
- hdu3642(三维转二维扫描线)
- css3中单位px,em,rem,vh,vw,vmin,vmax的区别及浏览器支持情况
- Git入门基本流程
- CCRenderTexture解析
- pwnable.kr simple login writeup
- Ext动态加载列
- Android Studio 快捷键
- 【图论】最大密度子图&权闭合图
- SQL Server: SELECT * 的真相: 索引覆盖(index coverage)