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);
    }
}
posted @ 2020-08-16 21:55  fxq1304  阅读(18)  评论(0编辑  收藏  举报