题意:给一些长方体,求这些长方体相交2次以上的体积
思路:在做过两维的之后做这个其实是一样的思路,先把z(第三维)处理了,然后在各个平面上面做扫描线(这里就和两维的一样了)
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
#define LL __int64
using namespace std;
const int maxn = 1010;
struct haha{int x1,x2,y1,y2,z1,z2;}s[maxn]; ///保存输入
struct node
{
int x,y1,y2,f;
node(){}
node(int xx,int yy1,int yy2,int ff)
{x=xx,y1=yy1,y2=yy2,f=ff;}
bool operator<(node a)const
{
if(x==a.x) return f < a.f;
return x < a.x;
}
}sa[maxn*2];
int Y[maxn*2],Z[maxn*2]; ///离散化坐标Y,Z
int T,n,y,z;
bool has[maxn]; ///表示这个长方体还在不在计算范围
vector<pair<int,int> >pp[maxn*2]; ///表示各个长方体插入或删除
int cov[maxn<<3],one[maxn<<3],two[maxn<<3],more[maxn<<3]; ///cov表示当前段覆盖,one,two,more表示覆盖1次,2次,多次
void pushup(int rt,int l,int r)
{
int ls = rt<<1,rs = rt<<1|1;
if(l==r) ls = 0,rs = 0; ///也可以再把数组开大2倍
if(cov[rt]==0)
{
more[rt] = more[ls] + more[rs];
two[rt] = two[ls] + two[rs];
one[rt] = one[ls] + one[rs];
}
if(cov[rt]==1)
{
more[rt] = two[ls] + two[rs] + more[ls] + more[rs];
two[rt] = one[ls] + one[rs];
one[rt] = Y[r+1] - Y[l] - two[rt] - more[rt];
}
if(cov[rt]==2)
{
more[rt] = one[ls] + one[rs] + two[ls] + two[rs] + more[ls] + more[rs];
two[rt] = Y[r+1] - Y[l] - more[rt];
one[rt] = 0;
}
if(cov[rt]==3)
{
more[rt] = Y[r+1] - Y[l];
one[rt] = two[rt] = 0;
}
}
void update(int L,int R,int x,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
cov[rt]+=x;
pushup(rt,l,r);
return;
}
int m = (l+r)/2;
if(L<=m) update(L,R,x,l,m,rt<<1);
if(R>m) update(L,R,x,m+1,r,rt<<1|1);
pushup(rt,l,r);
}
LL calc() ///扫描当前平面
{
LL res = 0;
int en = 0;
for(int i=0;i<n;i++)
if(has[i])
{
int y1 = lower_bound(Y,Y+y,s[i].y1)-Y;
int y2 = lower_bound(Y,Y+y,s[i].y2)-Y-1;
sa[en++] = node(s[i].x1,y1,y2,1);
sa[en++] = node(s[i].x2,y1,y2,-1);
}
sort(sa,sa+en);
memset(cov,0,sizeof(cov));
memset(one,0,sizeof(one));
memset(two,0,sizeof(two));
memset(more,0,sizeof(more));
for(int i=0;i<en-1;i++)
{
update(sa[i].y1,sa[i].y2,sa[i].f,0,y,1);
res += (LL)more[1]*(sa[i+1].x - sa[i].x);
}
return res;
}
int main()
{
scanf("%d",&T);
for(int ca=1;ca<=T;ca++)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d%d%d%d%d%d",&s[i].x1,&s[i].y1,&s[i].z1,&s[i].x2,&s[i].y2,&s[i].z2);
Y[i] = s[i].y1, Y[i+n] = s[i].y2;
Z[i] = s[i].z1, Z[i+n] = s[i].z2;
pp[i].clear(), pp[i+n].clear();
has[i] = 0;
}
sort(Z, Z+2*n);
z = unique(Z, Z+2*n) - Z;
sort(Y, Y+2*n);
y = unique(Y, Y+2*n) - Y;
for(int i=0;i<n;i++)
{
int t1 = lower_bound(Z, Z+z, s[i].z1)-Z;
int t2 = lower_bound(Z, Z+z, s[i].z2)-Z;
pp[t1].push_back(make_pair(i,1));
pp[t2].push_back(make_pair(i,-1));
}
LL ans = 0;
for(int i=0;i<z-1;i++) ///分开z个平面来分别做扫描线
{
for(int j=0;j<pp[i].size();j++)
{
if(pp[i][j].second>0)
has[pp[i][j].first]=1;
else
has[pp[i][j].first]=0;
}
ans += calc()*(Z[i+1]-Z[i]);
}
printf("Case %d: %I64d\n", ca, ans);
}
return 0;
}