题目链接:[ HDU - 3642 ]
题目大意:给你n个立方体的左下角坐标和右上角坐标,求立方体相交至少相交的面积。
题解
将Z轴离散化,把面积当作二维的底和高
代码如下
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2010;
struct Node
{
int l,r;
int lf,rf;//实际的左右端点
int c;
int once,twice,more;
}segTree[MAXN*3];
int y[MAXN];
int z[MAXN];
struct Line
{
int x;
int y1,y2;
int z1,z2;//这两个是枚举的时候判断使用的
int f;
}line[MAXN];
bool cmp(Line a,Line b)
{
return a.x<b.x;
}
void Build(int i,int l,int r)
{
segTree[i].l=l;
segTree[i].r=r;
segTree[i].lf=y[l];
segTree[i].rf=y[r];
segTree[i].c=0;
segTree[i].once=segTree[i].twice=segTree[i].more=0;
if(r==l+1)return;
int mid=(l+r)>>1;
Build(i<<1,l,mid);
Build((i<<1)|1,mid,r);
}
void push_up(int i)
{
if(segTree[i].c>2)
{
segTree[i].more=segTree[i].rf-segTree[i].lf;
segTree[i].once=segTree[i].twice=0;
}
else if(segTree[i].c==2)
{
if(segTree[i].l+1==segTree[i].r)//叶子结点
{
segTree[i].more=0;
segTree[i].twice=segTree[i].rf-segTree[i].lf;
segTree[i].once=0;
return;
}
segTree[i].more=segTree[i<<1].once+segTree[i<<1].twice+segTree[i<<1].more
+segTree[(i<<1)|1].once+segTree[(i<<1)|1].twice+segTree[(i<<1)|1].more;
segTree[i].twice=segTree[i].rf-segTree[i].lf-segTree[i].more;
segTree[i].once=0;
}
else if(segTree[i].c==1)
{
if(segTree[i].l+1==segTree[i].r)
{
segTree[i].more=0;
segTree[i].twice=0;
segTree[i].once=segTree[i].rf-segTree[i].lf;
return;
}
segTree[i].more=segTree[i<<1].more+segTree[i<<1].twice
+segTree[(i<<1)|1].more+segTree[(i<<1)|1].twice;
segTree[i].twice=segTree[i<<1].once+segTree[(i<<1)|1].once;
segTree[i].once=segTree[i].rf-segTree[i].lf-segTree[i].more-segTree[i].twice;
}
else
{
if(segTree[i].l+1==segTree[i].r)
{
segTree[i].more=segTree[i].once=segTree[i].twice=0;
return;
}
segTree[i].more=segTree[i<<1].more+segTree[(i<<1)|1].more;
segTree[i].twice=segTree[i<<1].twice+segTree[(i<<1)|1].twice;
segTree[i].once=segTree[i<<1].once+segTree[(i<<1)|1].once;
}
}
void update(int i,Line e)
{
if(segTree[i].lf>=e.y1 && segTree[i].rf<=e.y2)
{
segTree[i].c+=e.f;
push_up(i);
return;
}
if(e.y2<=segTree[i<<1].rf) update(i<<1,e);
else if(e.y1>=segTree[(i<<1)|1].lf) update((i<<1)|1,e);
else
{
Line temp=e;
temp.y2=segTree[i<<1].rf;
update(i<<1,temp);
temp=e;
temp.y1=segTree[(i<<1)|1].lf;
update((i<<1)|1,temp);
}
push_up(i);
}
Line temp[MAXN];
int main(void)
{
int T;
int n;
int x1,y1,z1,x2,y2,z2;
scanf("%d",&T);
int iCase=0;
while(T--)
{
iCase++;
scanf("%d",&n);
int t=0;
for(int i=0;i<n;i++)
{
scanf("%d%d%d%d%d%d", &x1, &y1, &z1, &x2, &y2, &z2);
line[t].x=x1;
line[t].y1=y1;
line[t].y2=y2;
line[t].z1=z1;
line[t].z2=z2;
line[t].f=1;
y[t]=y1;
z[t++]=z1;
line[t].x=x2;
line[t].y1=y1;
line[t].y2=y2;
line[t].z1=z1;
line[t].z2=z2;
line[t].f=-1;
y[t]=y2;
z[t++]=z2;
}
sort(line,line+t,cmp);
sort(y,y+t);
int t1=unique(y,y+t)-y;
Build(1,0,t1-1);
sort(z,z+t);
int t2=unique(z,z+t)-z;
long long ans=0;
long long area=0;
for(int i=0;i<t2-1;i++)
{
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];
area=0;
update(1,temp[0]);
for(int j=1;j<m;j++)
{
area+=(long long)segTree[1].more*(temp[j].x-temp[j-1].x);
update(1,temp[j]);
}
ans+=area*(z[i+1]-z[i]);
}
printf("Case %d: %I64d\n",iCase,ans);
}
return 0;
}