題目描述
A君近日爲準備省隊選拔,特意進行了數據結構的專項訓練。訓練過程中就遇到了“矩形面積並”這道經典問題,即:給出N個各邊與座標軸平行(垂直)的矩形,求矩形覆蓋的面積之和。A君按縱座標建立線段樹後按橫座標掃描計算,輕易AC了這道題,時間複雜度爲O(NlogN)。
爲了強化訓練,A君將問題推廣到三維空間中,即:給出N個各棱與座標軸平行(垂直)的立方體,求立方體覆蓋的體積之和。爲了簡化問題,令立方體均退化爲正立方體,用四元組(x, y, z, r)表示一個立方體,其中x, y, z爲立方體的中心點座標,r爲中心點到立方體各個面的距離(即立方體高的一半)。
這次可難住了A君,只好請你——未來的金牌——來幫助他了。
輸入格式
第一行是一個正整數N。
以下N行每行四個整數x, y, z, r,由空格隔開。
輸出格式
共一個數,即覆蓋的總體積。
樣例數據
樣例輸入
3
0 0 0 3
1 –1 0 1
19 3 5 6
樣例輸出
1944
數據規模和約定
對於 30% 的數據,1≤N≤5
對於 70% 的數據,1≤N≤30
對於 100% 的數據,1≤N≤100
對於 100% 的數據,-1000≤x, y, z≤1000,1≤r≤200
題目分析
和NOI97衛星覆蓋一毛一樣
那屆的同學們的確可以去拿金牌了
源代碼
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
inline const int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
const int maxn=3;
struct Cube {
double left[maxn],right[maxn];
} ;
struct Universal_Cut {
Cube a[10005];
int sum;
int init() {
sum=0;
}
bool if_intersect(Cube a,Cube b) {
for(int i=0; i<maxn; i++)
if(a.left[i]>=b.right[i]||a.right[i]<=b.left[i])return false;
return true;
}
void add(double x[maxn],double y[maxn]) {
sum++;
for(int i=0; i<maxn; i++) {
a[sum].left[i]=x[i];
a[sum].right[i]=y[i];
}
}
void del(int index) {
a[index]=a[sum];
sum--;
}
void cut(Cube a,Cube b,int dimension) { //返回交集
if(dimension==maxn)return;
double k1=max(a.left[dimension],b.left[dimension]);
double k2=min(a.right[dimension],b.right[dimension]);
if(a.left[dimension]<k1) {
Cube tmp=a;
tmp.right[dimension]=k1;
add(tmp.left,tmp.right);
}
if(k2<a.right[dimension]) {
Cube tmp=a;
tmp.left[dimension]=k2;
add(tmp.left,tmp.right);
}
a.left[dimension]=k1;
a.right[dimension]=k2;
cut(a,b,dimension+1);
}
};
Universal_Cut c;
int n,ans=0;
double Bleft[maxn],Bright[maxn];
int main() {
n=Get_Int();
for(int i=1; i<=n; i++) {
int x=Get_Int(),y=Get_Int(),z=Get_Int(),h=Get_Int();
Bleft[0]=x-h,Bleft[1]=y-h,Bleft[2]=z-h,Bright[0]=x+h,Bright[1]=y+h,Bright[2]=z+h;
Cube b;
for(int i=0; i<maxn; i++) {
b.left[i]=Bleft[i];
b.right[i]=Bright[i];
}
for(int j=1; j<=c.sum; j++) {
if(!c.if_intersect(c.a[j],b))continue;
c.cut(c.a[j],b,0);
c.del(j);
j--;
}
c.add(Bleft,Bright);
}
for(int i=1; i<=c.sum; i++) {
int tmp=1;
for(int j=0; j<maxn; j++)
tmp*=c.a[i].right[j]-c.a[i].left[j];
ans+=tmp;
}
printf("%d\n",ans);
return 0;
}