求三次及以上的长方体体积交
跟求体积并的唯一区别就是:push_up增加了2个判断,增加了once和twice两个记录
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int N=2005;
typedef long long LL;
struct node{
int x,y1,y2;
int f,z1,z2;
}lines[N],tlines[N];
int y[N],z[N];
int wide[N*4],num[N*4],once[N*4],twice[N*4];
int cmp(node a,node b){
return a.x<b.x;
}
void build(int l,int r,int rt){
wide[rt]=num[rt]=once[rt]=twice[rt]=0;
if(l==r)
return;
int m=(l+r)/2;
build(lson);
build(rson);
}
void push_up(int l, int r, int rt) {
if (num[rt] > 2){
wide[rt] = y[r+1] - y[l];
once[rt] = twice[rt] = 0;
return ;
}
if (num[rt] == 2){
if (l == r) {
twice[rt] = y[r+1] - y[l];
once[rt] = wide[rt] = 0;
}
else {
wide[rt] = wide[rt<<1] + wide[rt<<1|1] + twice[rt<<1] + twice[rt<<1|1] + once[rt<<1] + once[rt<<1|1];
twice[rt] = y[r+1] - y[l] - wide[rt];
once[rt] = 0;
}
return ;
}
if (num[rt] == 1) {
if (l == r) {
once[rt] = y[r+1] - y[l];
twice[rt] = wide[rt] = 0;
}
else {
wide[rt] = wide[rt<<1] + wide[rt<<1|1] + twice[rt<<1] + twice[rt<<1|1];
twice[rt] = once[rt<<1] + once[rt<<1|1];
once[rt] = y[r+1] - y[l] - twice[rt] - wide[rt];
}
return ;
}
if (num[rt] == 0){
if (l == r)
wide[rt] = twice[rt] = once[rt] = 0;
else{
wide[rt] = wide[rt<<1] + wide[rt<<1|1];
twice[rt] = twice[rt<<1] + twice[rt<<1|1];
once[rt] = once[rt<<1] + once[rt<<1|1];
}
return ;
}
}
void update(int a,int b,int c,int l,int r,int rt){//线段更新
if(a<=l&&b>=r){
num[rt]+=c;
push_up(l,r,rt);
return;
}
int m=(l+r)/2;
if(a<=m)
update(a,b,c,lson);
if(b>m)
update(a,b,c,rson);
push_up(l,r,rt);
}
void addlines(int x,int y1,int y2,int f,int z1,int z2,int cnt){
lines[cnt].x=x;
lines[cnt].y1=y1;
lines[cnt].y2=y2;
lines[cnt].f=f;
lines[cnt].z1=z1;
lines[cnt].z2=z2;
}
int main(){
int n,tt,t=1;
int x1,x2,y1,y2,z1,z2;
for(cin>>tt;t<=tt;t++){
cin>>n;
int cnt=0;
for(int i=0;i<n;i++){
scanf("%d %d %d %d %d %d",&x1,&y1,&z1,&x2,&y2,&z2);
addlines(x1,y1,y2,1,z1,z2,cnt);
z[cnt]=z1;
y[cnt++]=y1;
addlines(x2,y1,y2,-1,z1,z2,cnt);
z[cnt]=z2;
y[cnt++]=y2;
}
sort(z,z+cnt);
sort(y,y+cnt);
int nny=unique(y,y+cnt)-y;
int nnz=unique(z,z+cnt)-z;
sort(lines,lines+cnt,cmp);
LL ans=0;
for(int k=0;k<nnz;k++){//按高度扫描
build(0,nny-1,1);
int tcnt=0;
for(int i=0;i<cnt;i++)//筛选
if(z[k]>=lines[i].z1&&z[k]<lines[i].z2)
tlines[tcnt++]=lines[i];
for(int i=0;i<tcnt-1;i++){
int left=lower_bound(y,y+nny,tlines[i].y1)-y;
int right=lower_bound(y,y+nny,tlines[i].y2)-y-1;
update(left,right,tlines[i].f,0,nny-1,1);
ans+=(LL)wide[1]*(tlines[i+1].x-tlines[i].x)*(z[k+1]-z[k]);
}
}
printf("Case %d: %I64d\n",t,ans);
}
return 0;
}