Get The Treasury HDU - 3642(体积扫描线)
Posted h-riven
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 ", cas++, ans); } return 0; }
以上是关于Get The Treasury HDU - 3642(体积扫描线)的主要内容,如果未能解决你的问题,请参考以下文章
HDU-3642 Get The Treasury(扫描线 + 离散化 + 线段树)
HDU3642 Get The Treasury —— 求矩形交体积 线段树 + 扫描线 + 离散化
Get The Treasury HDU - 3642(体积扫描线)