#扫描线,线段树#洛谷 5567 [SDOI2008] 立方体覆盖
分析
将 \(z\) 轴离散化,将相邻的两个坐标间包含的立方体加进来,相当于是查询面积,
面积的部分用扫描线,相当于体积就是面积乘高,时间复杂度 \(O(n^2\log n)\)
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
const int N=211; struct rec{int x,l,r,z;}b[N];
int lazy[N<<2],w[N<<2],n,tot,sum,a[N],_a[N],_m,X[N],Y[N],Z[N],R[N],m,ans;
int iut(){
int ans=0,f=1; char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
bool cmp(rec x,rec y){return (x.x^y.x)?(x.x<y.x):(x.z>y.z);}
void update(int k,int l,int r,int x,int y,int z){
if (l==x&&r==y){
lazy[k]+=z;
if (lazy[k]) w[k]=a[r+1]-a[l];
else if (l==r) w[k]=0;
else w[k]=w[k<<1]+w[k<<1|1];
return;
}
int mid=(l+r)>>1;
if (y<=mid) update(k<<1,l,mid,x,y,z);
else if (x>mid) update(k<<1|1,mid+1,r,x,y,z);
else update(k<<1,l,mid,x,mid,z),update(k<<1|1,mid+1,r,mid+1,y,z);
if (lazy[k]) w[k]=a[r+1]-a[l];
else w[k]=w[k<<1]+w[k<<1|1];
}
void Clear(int k,int l,int r){
lazy[k]=w[k]=0;
if (l==r) return;
int mid=(l+r)>>1;
Clear(k<<1,l,mid);
Clear(k<<1|1,mid+1,r);
}
int main(){
n=iut();
for (int i=1;i<=n;++i){
X[i]=iut(),Y[i]=iut(),Z[i]=iut(),R[i]=iut();
_a[++_m]=Z[i]-R[i],_a[++_m]=Z[i]+R[i];
}
sort(_a+1,_a+1+_m),_m=unique(_a+1,_a+1+_m)-_a-1;
for (int o=1;o<_m;++o){
tot=sum=m=0;
for (int i=1;i<=n;++i)
if (Z[i]-R[i]<=_a[o]&&_a[o+1]<=Z[i]+R[i]){
b[++tot]=(rec){X[i]-R[i],Y[i]-R[i],Y[i]+R[i],1};
b[++tot]=(rec){X[i]+R[i],Y[i]-R[i],Y[i]+R[i],-1};
a[++m]=Y[i]-R[i],a[++m]=Y[i]+R[i];
}
if (!m) continue;
sort(a+1,a+1+m),m=unique(a+1,a+1+m)-a-1;
sort(b+1,b+1+tot,cmp);
for (int i=1;i<tot;++i){
b[i].l=lower_bound(a+1,a+1+m,b[i].l)-a;
b[i].r=lower_bound(a+1,a+1+m,b[i].r)-a-1;
update(1,1,m,b[i].l,b[i].r,b[i].z);
sum+=(b[i+1].x-b[i].x)*w[1];
}
ans+=(_a[o+1]-_a[o])*sum;
Clear(1,1,m);
}
return !printf("%d",ans);
}

浙公网安备 33010602011771号