卫星覆盖(NOI1997)
题面:
SERCOI(Space-Earth Resource Cover-Observe lnstitute) 是一个致力于利用卫星技术对空间和地球资源进行覆盖观测的组织。现在他们研制成功一种新型资源观测卫星 -SERCOI-308。这种卫星可以覆盖空间直角坐标系中一定大小的立方体空间,卫星处于该立方体的中心。 其中 (x,y,z)(x,y,z) 为立方体的中心点坐标, rr 为此中心点到立方体各个面的距离(即 rr 为立方体高的一半).立方体的各条边均平行于相应的坐标轴。我们可以用一个四元组 (x,y,z,r)(x,y,z,r) 描述一颗卫星的状态,它所能覆盖的空间体积 。 由于一颗卫星所能覆盖的空间体积是有限的,因此空间中可能有若干颗卫星协同工作。它们所覆盖的空间区域可能有重叠的地方,如下图所示(阴影部分表示重叠的区域)。
写一个程序,根据给定的卫星分布情况,计算它们所覆盖的总体积。
思路
第一道自己做的NOI的题。
说白了就是求三维立方体的覆盖体积。
我们继承我们二维的思想,也就是用扫描线和线段树来求矩形的面积并。
扩展到三维上,也就是我们把他分割成很多高度为一的层,然后对于每一个层去做二维的面积并。
然后答案就是每一个层的二维面积并的和。
时间复杂度:。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int n;
struct owl{
int x,y1,y2;
int k;
bool operator < (const owl & t)const{
return x < t.x;
}
}seg[N * 2];
struct hoot{
int l,r;
int cnt;
int len;
}tr[N * 8];
vector<int>ys;
int find(int y){
return lower_bound(ys.begin(), ys.end(), y) - ys.begin();
}
void pushup(int u){
if (tr[u].cnt){
tr[u].len = ys[tr[u].r + 1] - ys[tr[u].l];
}
else if (tr[u].l != tr[u].r){
tr[u].len = tr[u << 1].len + tr[u << 1 | 1].len;
}
else{
tr[u].len = 0;
}
}
void build(int u,int l,int r){
tr[u] = {l,r,0,0};
if (l != r){
int mid = l + r >> 1;
build(u << 1,l,mid),build(u << 1 | 1,mid + 1,r);
}
}
void modify(int u,int l,int r,int k){
if (tr[u].l >= l && tr[u].r <= r){
tr[u].cnt += k;
pushup(u);
}
else{
int mid = tr[u].l + tr[u].r >> 1;
if (l <= mid){
modify(u << 1,l,r,k);
}
if (r > mid){
modify(u << 1 | 1,l,r,k);
}
pushup(u);
}
}
struct DID{
int x,y,z,d;
}v[N];
struct SOREN{
int x1,y1,x2,y2;
};
int main(){
cin >> n;
for (int i = 1; i <= n; i ++ ){
cin >> v[i].x >> v[i].y >> v[i].z >> v[i].d;
}
int ans = 0;
for (int Z = -1000; Z <= 1000; Z ++ ){
ys.clear();
int m = 0;
vector<SOREN>vec;
for (int i = 1; i <= n; i ++ ){
int x1 = -3000, y1 = -3000, x2 = -3000, y2 = -3000;
if (Z >= v[i].z - v[i].d + 1 && Z <= v[i].z + v[i].d){
x1 = v[i].x - v[i].d,x2 = v[i].x + v[i].d;
y1 = v[i].y - v[i].d,y2 = v[i].y + v[i].d;
}
if (x1 == -3000 && y1 == -3000 && x2 == -3000 && y2 == -3000){
continue;
}
seg[m ++ ] = {x1, y1, y2, 1};
seg[m ++ ] = {x2, y1, y2, -1};
vec.push_back({x1,y1,x2,y2});
ys.push_back(y1), ys.push_back(y2);
}
if (vec.size() == 1){
ans += (vec[0].x2 - vec[0].x1) * (vec[0].y2 - vec[0].y1);
continue;
}
if (m > 0){
sort(ys.begin(), ys.end());
ys.erase(unique(ys.begin(), ys.end()), ys.end());
build(1, 0, ys.size() - 2);
sort(seg, seg + m);
int res = 0;
for (int i = 0; i < m; i ++ ){
if (i > 0){
res += (tr[1].len) * (seg[i].x - seg[i - 1].x);
}
modify(1, find(seg[i].y1), find(seg[i].y2) - 1, seg[i].k);
}
ans += res;
}
}
cout << ans;
return 0;
}