#扫描线,线段树#洛谷 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);
} 
posted @ 2025-07-12 23:51  lemondinosaur  阅读(12)  评论(0)    收藏  举报