标签:区间 return hdu pac lse == clu 部分 bsp
三维扫描线,枚举z寻找相交区间的立方体,然后直接扫描线求xy平面的相交三次及以上面积,乘以z区间求和就可以了
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; const int maxn=1e6+100; const int maxm=2000+500; int col[maxn<<2]; int len1[maxn<<2],len2[maxn<<2],sum[maxn<<2];//重合线段分别为1 2 3 的线段长度 int zz[maxm],xx[maxm]; typedef long long ll; int t,n; struct Point { int x,y,z; void read() { scanf("%d%d%d",&x,&y,&z); } }; struct graphic { Point a,b; }gg[maxm]; struct note { int l,r,h; int z; int ff; note() {} note(int l,int r,int h,int ff):l(l),r(r),h(h),ff(ff) {} bool operator <(const note &p) const { return h<p.h; } }aa[maxm]; void pushup(int l,int r,int rt) { if(col[rt]>=3) { sum[rt]=xx[r+1]-xx[l]; len1[rt]=len2[rt]=0; } else if(col[rt]==2) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]+len1[rt<<1]+len1[rt<<1|1]+len2[rt<<1]+len2[rt<<1|1]; len2[rt]=xx[r+1]-xx[l]-sum[rt];//总长度减去重合次数>=3的部分才是重合次数==2的部分 len1[rt]=0; } else if(col[rt]==1) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]+len2[rt<<1]+len2[rt<<1|1]; len2[rt]=len1[rt<<1]+len1[rt<<1|1]; len1[rt]=xx[r+1]-xx[l]-sum[rt]-len2[rt];//总长度减去重合次数>=和==2的部分才是重合次数==1的部分 } else if(l==r) { sum[rt]=len1[rt]=len2[rt]=0; } else { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; len1[rt]=len1[rt<<1]+len1[rt<<1|1]; len2[rt]=len2[rt<<1]+len2[rt<<1|1]; } } void update(int L,int R,int v,int l,int r,int rt) { if(L<=l&&r<=R) { col[rt]+=v; pushup(l,r,rt); return; } int mid=(l+r)>>1; if(L<=mid) update(L,R,v,l,mid,rt<<1); if(mid<R) update(L,R,v,mid+1,r,rt<<1|1); pushup(l,r,rt); } int main() { scanf("%d",&t); int Case=0; while(t--) { scanf("%d",&n); int cx=0,cz=0; for(int i=1;i<=n;i++) { gg[i].a.read(); gg[i].b.read(); zz[cz++]=gg[i].a.z; zz[cz++]=gg[i].b.z; xx[cx++]=gg[i].a.x; xx[cx++]=gg[i].b.x; } printf("Case %d: ",++Case); if(n<3) { printf("0\n"); continue; } sort(zz,zz+cz); sort(xx,xx+cx); cz=unique(zz,zz+cz)-zz; cx=unique(xx,xx+cx)-xx; int nn=2000+10; ll ans=0; for(int j=0;j<cz-1;j++)//离散化z后枚举区间,寻找各个立方体和区间重合的部分 { int cnt=0; for(int i=1;i<=n;i++) { if(gg[i].a.z<=zz[j]&&gg[i].b.z>zz[j])//枚举的区间是离散化z后的,所以必然小于任意一个立方体的高 { aa[++cnt]=note(gg[i].a.x,gg[i].b.x,gg[i].a.y,1); aa[++cnt]=note(gg[i].a.x,gg[i].b.x,gg[i].b.y,-1); } } sort(aa+1,aa+cnt+1); ll sss=0; for(int i=1;i<=cnt;i++) { int hl=lower_bound(xx,xx+cx,aa[i].l)-xx; int hr=lower_bound(xx,xx+cx,aa[i].r)-xx; sss+=(ll)sum[1]*(ll)(aa[i].h-aa[i-1].h); update(hl,hr-1,aa[i].ff,0,nn,1); } ans+=sss*(ll)(zz[j+1]-zz[j]);//重合三次后的面积乘以高 } printf("%lld\n",ans); } return 0; }
标签:区间 return hdu pac lse == clu 部分 bsp
原文地址:https://www.cnblogs.com/Wangwanxiang/p/9441834.html