Get The Treasury HDU - 3642(体积扫描线)

给出n个立方体,要你求这些立方体至少被覆盖三次的部分。

先把这个立方体的信息存在来,发现Z的范围不大,z范围是是[-500,500],所以我们可以先离散化,然后枚举Z,

然后对于每一段Z的区域内,在当前的区域内对xoy轴使用一次扫描线,找到当前这个区域内被覆盖三次的体积,然后每次枚举Z,每次相加,就是最后的答案。

#include<map>
#include<set>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define first fi
#define second se
#define lowbit(x) (x & (-x))

typedef unsigned long long int ull;
typedef long long int ll;
const double pi = 4.0*atan(1.0);
const int inf = 0x3f3f3f3f;
const int maxn = 2050;
const int maxm = 305;
using namespace std;

int n, m, tol, T;
struct Node {
    int l, r, h, f;
    bool operator < (Node a) const {
        return h < a.h;
    }
};
Node node[maxn];
struct Edge {
    int x1, y1, z1;
    int x2, y2, z2;
};
Edge edge[maxn];
int Z[maxn];
int a[maxn];
int cnt[maxn << 2];
int sum1[maxn << 2];
int sum2[maxn << 2];
int sum3[maxn << 2];

void init() {
    m = 1;
    memset(cnt, 0, sizeof cnt);
    memset(sum1, 0, sizeof sum1);
    memset(sum2, 0, sizeof sum2);
    memset(sum3, 0, sizeof sum3);
    memset(node, 0, sizeof node);
}

void pushup(int left, int right, int root) {
    if(cnt[root] >= 3) {
        sum3[root] = sum2[root] = sum1[root] = a[right+1] - a[left];
    } else if(cnt[root] == 2) {
        sum2[root] = sum1[root] = a[right+1] - a[left];
        sum3[root] = sum1[root << 1] + sum1[root << 1 | 1];
    } else if(cnt[root] == 1) {
        sum1[root] = a[right+1] - a[left];
        sum3[root] = sum2[root << 1] + sum2[root << 1 | 1];
        sum2[root] = sum1[root << 1] + sum1[root << 1 | 1];
    } else {
        sum3[root] = sum3[root << 1] + sum3[root << 1 | 1];
        sum2[root] = sum2[root << 1] + sum2[root << 1 | 1];
        sum1[root] = sum1[root << 1] + sum1[root << 1 | 1];
    }
}

void update(int left, int right, int prel, int prer, int val, int root) {
    if(prel <= left && right <= prer) {
        cnt[root] += val;
        pushup(left, right, root);
        return ;
    }
    int mid = (left + right) >> 1;
    if(prel <= mid)    update(left, mid, prel, prer, val, root << 1);
    if(prer > mid)    update(mid+1, right, prel, prer, val, root << 1 | 1);
    pushup(left, right, root);
}

int main() {
    int T;
    scanf("%d", &T);
    int cas = 1;
    while(T--) {
        memset(edge, 0, sizeof edge);
        memset(Z, 0, sizeof Z);
        scanf("%d", &n);
        for(int i=1; i<=n; i++) {
            int x, y, z;
            scanf("%d%d%d", &x, &y, &z);
            edge[i].x1 = x;
            edge[i].y1 = y;
            edge[i].z1 = z;
            Z[2*i-1] = z;
            scanf("%d%d%d", &x, &y, &z);
            edge[i].x2 = x;
            edge[i].y2 = y;
            edge[i].z2 = z;
            Z[2*i] = z;
        }
        sort(Z+1, Z+1+2*n);
        int zz = unique(Z+1, Z+1+2*n) - (Z+1);
        ll ans = 0;
        for(int i=1; i<zz; i++) {
            init();
            for(int j=1; j<=n; j++) {
                if(edge[j].z1 <= Z[i] && Z[i+1] <= edge[j].z2) {
                    node[m].l = edge[j].x1;
                    node[m].r = edge[j].x2;
                    node[m].h = edge[j].y1;
                    node[m].f = 1;
                    a[m++] = edge[j].x1;
                    node[m].l = edge[j].x1;
                    node[m].r = edge[j].x2;
                    node[m].h = edge[j].y2;
                    node[m].f = -1;
                    a[m++] = edge[j].x2;
                }
            }
            m--;
            sort(node+1, node+1+m);
            sort(a+1, a+1+m);
            int nn = unique(a+1, a+1+m) - (a+1);
            for(int j=1; j<m; j++) {
                int l = lower_bound(a+1, a+1+nn, node[j].l) - a;
                int r = lower_bound(a+1, a+1+nn, node[j].r) - a;
                update(1, m, l, r-1, node[j].f, 1);
                ans += 1ll * sum3[1] * (node[j+1].h - node[j].h) * (Z[i+1] - Z[i]);
            }
        }
        printf("Case %d: %lld\n", cas++, ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/H-Riven/p/9360502.html

时间: 2024-11-05 22:44:05

Get The Treasury HDU - 3642(体积扫描线)的相关文章

Q - Get The Treasury - HDU 3642 (扫面线求体积)

题意:求被三个或三个以上立方体重合的体积 分析:就是平面面积的加强,不过归根还是一样的,可以把z轴按照从小向大分区间N个,然后可以得到N个平面,用平面重复三次以上的在和高度计算体积. ************************************************************************ #include<stdio.h>#include<algorithm>using namespace std; #define Lson r<<

hdu 3642 体积并

题意:求三个矩形体积的并 链接:点我 枚举z 1 #include<stdio.h> 2 #include<iostream> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<algorithm> 6 #include<vector> 7 #include<math.h> 8 #include<map> 9 #pragma comment(linker,

hdu 3642 Get The Treasury (三维的扫描线)

题目大意: 给出N个立方体. 求一个三维空间中被包围三次的空间的体积之和. 思路分析: 发现Z的范围很小.那么我们可以枚举Z轴,然后对 x y做扫描线. 而且不用枚举所有的Z ,只需要将Z离散化之后枚举. #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define maxn 2222 #define debug puts("fuck!&q

hdu 3642 Get The Treasury(扫描线)

题目链接:hdu 3642 Get The Treasury 题目大意:三维坐标系,给定若干的长方体,问说有多少位置被覆盖3次以上. 解题思路:扫描线,将第三维分离出来,就是普通的二维扫描线,然后对于每个节点要维护覆盖0,1,2,3以上这4种的覆盖面积. #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const

HDU 3642 Get The Treasury 线段树+扫描线

反向标记是错的,要对矩形进行拆分 #include <cstdio> #include <algorithm> #include <cstring> #include <vector> typedef long long LL; using namespace std; #define lson rt << 1,l,mid #define rson rt << 1 | 1,mid + 1,r const int maxn = 5e4

HDU 3642 线段树+离散化+扫描线

题意:给你N个长方体的左下角和右上角坐标,问你空间中有多少体积是被大于两个不同的立方体覆盖的.x,y~10^6 z~500 考虑到给的z比较小,所以可以直接枚举z,然后跑二维的扫描线就好. 关于处理被不同的线段覆盖三次的问题,可以维护四个信息,cnt,once,twice,more,然后相互推出结果就好. #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #

HDU 3642 Get The Treasury(线段树)

HDU 3642 Get The Treasury 题目链接 题意:给定一些立方体,求体积重叠超过3次的 思路:由于z坐标只有500,那么就可以枚举z坐标,每次做x,y的面积并即可,用线段树维护 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 1005; const int INF = 0x3f3f3f3f; typedef

HDU 1255 离散化+扫描线覆盖的面积

覆盖的面积 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3571    Accepted Submission(s): 1753 Problem Description 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input 输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据

HDU 3642 - Get The Treasury - [加强版扫描线+线段树]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description Jack knows that there is a great underground treasury in a secret region. And he has a special d