题解 P5567 【[SDOI2008]立方体覆盖】
feecle6418 · · 题解
矩形切割裸题。
什么叫矩形切割?就是维护一个不相交矩形组成的集合,支持插入。不过这道题维护的是立方体,思想是一样的。
结合核心代码讲解如下:
void Add(int x1,int y1,int z1,int x2,int y2,int z2){
a[++tot]=(Cube){x1,y1,z1,x2,y2,z2};//加入新长方体
}
void Cut(int i,int x1,int y1,int z1,int x2,int y2,int z2,int z){
//z表示维度
if(!z){
int k1=max(x1,a[i].x1),k2=min(x2,a[i].x2);
//得到Cut后长方体顶点的x坐标
if(a[i].x1<k1)Add(a[i].x1,a[i].y1,a[i].z1,k1,a[i].y2,a[i].z2);
//将原长方体Cut成这个新长方体两边的两部分,这是左边
if(k2<a[i].x2)Add(k2,a[i].y1,a[i].z1,a[i].x2,a[i].y2,a[i].z2);
//右边
Cut(i,k1,y1,z1,k2,y2,z2,1);
//另外一个维度上也一样
}
else if(z==1){
int k1=max(y1,a[i].y1),k2=min(y2,a[i].y2);
if(a[i].y1<k1)Add(x1,a[i].y1,a[i].z1,x2,k1,a[i].z2);//y、z维上同理
if(k2<a[i].y2)Add(x1,k2,a[i].z1,x2,a[i].y2,a[i].z2);
Cut(i,x1,k1,z1,x2,k2,z2,2);
}
else {
int k1=max(z1,a[i].z1),k2=min(z2,a[i].z2);
if(a[i].z1<k1)Add(x1,y1,a[i].z1,x2,y2,k1);
if(k2<a[i].z2)Add(x1,y1,k2,x2,y2,a[i].z2);
}
}
主程序中调用如下:
for(int i=1,x,y,z,r;i<=q;i++){
scanf("%d%d%d%d",&x,&y,&z,&r);
int x1=x-r,x2=x+r,y1=y-r,y2=y+r,z1=z-r,z2=z+r;//长方体的顶点
for(int j=1;j<=tot;j++){
if(a[j].x1>=x2||a[j].y1>=y2||a[j].x2<=x1||a[j].y2<=y1||a[j].z1>=z2||a[j].z2<=z1)continue;//若不相交则跳过,不用切割
Cut(j,x1,y1,z1,x2,y2,z2,0);//切割原长方体
a[j]=a[tot],j--,tot--;//删除原长方体(原长方体已经被分成许多与现在的长方体不相交的小长方体)
}
Add(x1,y1,z1,x2,y2,z2);
}