题解 [SDOI2008]立方体覆盖

题目描述

A君近日为准备省队选拔,特意进行了数据结构的专项训练。训练过程中就遇到了“矩形面积并”这道经典问题,即:给出 NN 个各边与坐标轴平行(垂直)的矩形,求矩形覆盖的面积之和。A君按纵坐标建立线段树后按横坐标扫描计算,轻易 AC 了这道题,时间复杂度为 O(N\log N)O(NlogN)。

为了强化训练,A君将问题推广到三维空间中,即:给出 NN 个各棱与坐标轴平行(垂直)的立方体,求立方体覆盖的体积之和。为了简化问题,令立方体均退化为正立方体,用四元组 (x, y, z, r)(x,y,z,r) 表示一个立方体,其中 x, y, zx,y,z 为立方体的中心点坐标,rr 为中心点到立方体各个面的距离(即立方体高的一半)。

这次可难住了A君,只好请你——未来的金牌——来帮助他了。

输入格式

第一行是一个正整数 NN。

以下 NN 行每行四个整数 x, y, z, rx,y,z,r。

输出格式

输出覆盖的总体积。

输入输出样例

输入 #1
3
0 0 0 3
1 –1 0 1
19 3 5 6
输出 #1
1944

说明/提示

N \leq 100, -1000 \leq x,y,z \leq 1000, r \leq 200N100,1000x,y,z1000,r200

-------------------------------------------------------------------------------------------------------------------------

这题的数据范围暗示了一切。

没错,就是一道大暴力

那么就构想一下怎么暴力吧(虽说各位大佬已经切了这道题


既然是三维空间,那么就可以考虑转化为二维情况,发现只要暴力枚举一下二维平面的坐标点,再另外处理一下第三维就行了。(卡常还是比较轻松的


详见代码

#include<bits/stdc++.h>
#define LL long long
#define Maxn 110
using namespace std;

struct Sq{
    int xb,xe,yb,ye,zb,ze;
}a[Maxn];

struct Node{
    int b,e;
}c[Maxn];

int ans;

inline int read(){
    int x = 0,f = 1;char ch = getchar();
    while (!isdigit(ch)){if (ch == '-') f = -1; ch = getchar(); }
    while (isdigit(ch)){x = (x << 3) + (x << 1) + ch - 48; ch = getchar(); }
    return (f==1)?x:-x;
}

inline bool cmp(Sq x,Sq y){
    if (x.zb != y.zb) return x.zb < y.zb;
    return x.ze < y.ze;
}

int main(){
    freopen("cover.in","r",stdin);
    freopen("cover.out","w",stdout);
    int n = read();
    int bx = 1e9, by = 1e9, ex = -1e9, ey = -1e9;//优化一下暴力,记开始位置和结束位置,然后枚举一下
    for (int i = 1; i <= n; i++){
        int x = read() + 1200, y = read() + 1200, z = read() + 1200, d = read();
        a[i].xb = x - d + 1, a[i].xe = x + d;
        bx = min(a[i].xb, bx), ex = max(a[i].xe, ex);
        a[i].yb = y - d + 1, a[i].ye = y + d;
        by = min(a[i].yb, by), ey = max(a[i].ye, ey);
        a[i].zb = z - d + 1, a[i].ze = z + d;
    }
    sort(a + 1, a + n + 1, cmp);//按照z轴排序,优先考虑开始位置下面的立方体,这样统计区间时方便一些
    for (int i = bx; i <= ex; i++){
        for (int j = by; j <= ey; j++){
            int cnt=0;
            for (int k = 1; k <= n; k++)
                if (i >= a[k].xb && i <= a[k].xe && j >= a[k].yb && j <= a[k].ye)
                    if (c[cnt].e < a[k].zb) c[++cnt] = (Node){a[k].zb, a[k].ze};
                    else c[cnt].e = max(a[k].ze, c[cnt].e);
            for (int k = 1; k <= cnt; k++) ans += c[k].e - c[k].b + 1;//统计区间
        }
    }
    printf("%d\n",ans);
    return 0;
}

%%Modest XXX:\ 这么丑的码风,我不想看(又被diss了)

posted @ 2019-10-13 15:36  Alpha_HzH  阅读(212)  评论(0编辑  收藏  举报