hdu3642 线段树+扫描线计算立方体体积
hdu3642 Get The Treasury
传送门
题意
有\(n(1\leq n \leq 1000)\)个立方体,每个立方体的左下角坐标为\((x_1,y_1,z_1)\),右上角坐标为\((x_2,y_2,z_2)\),其中\(x\)坐标和\(y\)坐标的绝对值不超过\(1e6\),\(z\)坐标的绝对值不超过\(500\)。计算三维空间中至少被覆盖三次的体积
题解
线段树+扫描线
由于\(z\)坐标范围比较小,所以离散化之后枚举\(z\)坐标,之后按照二维平面计算重叠面积的方法计算,线段树节点维护\(4\)个变量:
cnt:当前区间被覆盖的次数
sum:当前区间被覆盖至少三次的实际长度
s:当前区间被覆盖恰好一次的实际长度
ss:当前区间被覆盖恰好两次的实际长度
#include<bits/stdc++.h>
#define LL long long
#define PII pair<int,int>
#define PLI pair<LL,int>
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define lowbit(x) (x&(-x))
using namespace std;
const int maxn=1010;
int T,n,X[2*maxn],Z[2*maxn],cnt_x,cnt_z,m;
struct cube{
int x11,y11,z11;
int x22,y22,z22;
}cubes[maxn];
struct node{
int l,r,h,state;
node(){}
node(int l,int r,int h,int state):l(l),r(r),h(h),state(state){}
bool operator < (const node& t)const{
return h<t.h;
}
}nodes[2*maxn];
struct SGT{
int cnt,sum,s,ss;
}sgt[8*maxn];
int binary_search(int x){
int l=1,r=cnt_x;
while(r>=l){
int mid=(l+r)>>1;
if(X[mid]==x) return mid;
if(X[mid]>x) r=mid-1;
else l=mid+1;
}
return -1;
}
void pushup(int o,int l,int r){
if(sgt[o].cnt>=3){
sgt[o].sum=X[r+1]-X[l];
sgt[o].s=sgt[o].ss=0;
}
else if(sgt[o].cnt==2){
if(l==r){
sgt[o].sum=0;
sgt[o].ss=X[r+1]-X[l];
sgt[o].s=0;
}
else{
sgt[o].sum=sgt[o<<1].sum+sgt[o<<1|1].sum+sgt[o<<1].s+sgt[o<<1|1].s+sgt[o<<1].ss+sgt[o<<1|1].ss;
sgt[o].ss=X[r+1]-X[l]-sgt[o].sum;
sgt[o].s=0;
}
}
else if(sgt[o].cnt==1){
if(l==r){
sgt[o].sum=sgt[o].ss=0;
sgt[o].s=X[r+1]-X[l];
}
else{
sgt[o].sum=sgt[o<<1].sum+sgt[o<<1|1].sum+sgt[o<<1].ss+sgt[o<<1|1].ss;
sgt[o].ss=sgt[o<<1].s+sgt[o<<1|1].s;
sgt[o].s=X[r+1]-X[l]-sgt[o].sum-sgt[o].ss;
}
}
else{
if(l==r){
sgt[o].sum=sgt[o].ss=sgt[o].s=0;
}
else{
sgt[o].sum=sgt[o<<1].sum+sgt[o<<1|1].sum;
sgt[o].s=sgt[o<<1].s+sgt[o<<1|1].s;
sgt[o].ss=sgt[o<<1].ss+sgt[o<<1|1].ss;
}
}
}
void build(int o,int l,int r){
sgt[o].cnt=sgt[o].sum=sgt[o].s=sgt[o].ss=0;
if(l==r) return;
int mid=(l+r)>>1;
build(lson);
build(rson);
pushup(o,l,r);
}
void update(int o,int l,int r,int ql,int qr,int v){
if(ql<=l && r<=qr){
sgt[o].cnt+=v;
pushup(o,l,r);
return;
}
int mid=(l+r)>>1;
if(ql<=mid) update(lson,ql,qr,v);
if(qr>mid) update(rson,ql,qr,v);
pushup(o,l,r);
}
int main(){
scanf("%d",&T);
for(int cas=1;cas<=T;cas++){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d %d %d",&cubes[i].x11,&cubes[i].y11,&cubes[i].z11);
scanf("%d %d %d",&cubes[i].x22,&cubes[i].y22,&cubes[i].z22);
}
cnt_x=cnt_z=0;
for(int i=1;i<=n;i++){
X[++cnt_x]=cubes[i].x11;
X[++cnt_x]=cubes[i].x22;
Z[++cnt_z]=cubes[i].z11;
Z[++cnt_z]=cubes[i].z22;
}
sort(X+1,X+1+cnt_x);
sort(Z+1,Z+1+cnt_z);
cnt_x=unique(X+1,X+1+cnt_x)-(X+1);
cnt_z=unique(Z+1,Z+1+cnt_z)-(Z+1);
LL ans=0;
for(int i=1;i<cnt_z;i++){
m=0;
for(int j=1;j<=n;j++){
if(cubes[j].z11<=Z[i] && cubes[j].z22>Z[i]){
nodes[++m]=node(cubes[j].x11,cubes[j].x22,cubes[j].y11,1);
nodes[++m]=node(cubes[j].x11,cubes[j].x22,cubes[j].y22,-1);
}
}
sort(nodes+1,nodes+1+m);
build(1,1,cnt_x-1);
LL res=0;
for(int j=1;j<m;j++){
int l=binary_search(nodes[j].l);
int r=binary_search(nodes[j].r)-1;
update(1,1,cnt_x-1,l,r,nodes[j].state);
res+=1ll*sgt[1].sum*(nodes[j+1].h-nodes[j].h);
}
ans+=res*(Z[i+1]-Z[i]);
}
printf("Case %d: %lld\n",cas,ans);
}
}