POJ 3642 长方体体积并 线段树 扫描线
来源:互联网 发布:qzj网络用语 编辑:程序博客网 时间:2024/06/02 14:37
这题就是给出了好多个长方体, 求出那些被覆盖了 3次及以上的体积
我们注意到z的范围很小,而且就给了1000个长方体
那么可以把z坐标离散化
然后在相邻的z坐标空间内,就变成了求面积覆盖
记录三个变量,代表一次覆盖,两次覆盖,三次覆盖及以上
#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cstdio>#include <cmath>#include <queue>#include <map>#include <set>#define eps 1e-5#define MAXN 2222#define MAXM 5555#define INF 100000007#define lch(x) x<<1#define rch(x) x<<1|1#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;struct Seg{ int l, r, h; int s; Seg(){} Seg(int a, int b, int c, int d){l = a; r = b; h = c; s = d;} bool operator <(const Seg &cmp)const { if(cmp.h == h) return s > cmp.s; return h < cmp.h; }}seg[MAXN];struct Spot{ int lx, rx, ly, ry, lz, rz;}p[MAXN];int x[MAXN], z[MAXN];int sum[4 * MAXN], sum2[4 * MAXN], sum3[4 * MAXN], cnt[4 * MAXN];int bin(int low, int high, int v){ while(low <= high) { int mid = (low + high) >> 1; if(x[mid] == v) return mid; else if(x[mid] > v) high = mid - 1; else low = mid + 1; } return -1;}void up(int rt, int l, int r){ if(cnt[rt] >= 3) sum[rt] = sum2[rt] = 0, sum3[rt] = x[r + 1] - x[l]; else if(cnt[rt] == 2) { if(l == r) sum2[rt] = x[r + 1] - x[l], sum3[rt] = 0, sum[rt] = 0; else { sum3[rt] = sum[lch(rt)] + sum[rch(rt)] + sum2[lch(rt)] + sum2[rch(rt)] + sum3[lch(rt)] + sum3[rch(rt)]; sum2[rt] = x[r + 1] - x[l] - sum3[rt]; sum[rt] = 0; } } else if(cnt[rt] == 1) { if(l == r) sum[rt] = x[r + 1] - x[l], sum2[rt] = 0, sum3[rt] = 0; else { sum3[rt] = sum2[lch(rt)] + sum2[rch(rt)] + sum3[lch(rt)] + sum3[rch(rt)]; sum2[rt] = sum[lch(rt)] + sum[rch(rt)]; sum[rt] = x[r + 1] - x[l] - sum2[rt] - sum3[rt]; } } else { if(l == r) sum[rt] = sum2[rt] = sum3[rt] = 0; else { sum3[rt] = sum3[lch(rt)] + sum3[rch(rt)]; sum2[rt] = sum2[lch(rt)] + sum2[rch(rt)]; sum[rt] = sum[lch(rt)] + sum[rch(rt)]; } }}void update(int L, int R, int v, int l, int r, int rt){ if(L <= l && R >= r) { cnt[rt] += v; up(rt, l, r); return; } int m = (l + r) >> 1; if(L <= m) update(L, R, v, lson); if(R > m) update(L, R, v, rson); up(rt, l, r);}int main(){ int T, n, cas = 0; scanf("%d", &T); while(T--) { scanf("%d", &n); int m = 0; for(int i = 1; i <= n; i++) { scanf("%d%d%d%d%d%d", &p[i].lx, &p[i].ly, &p[i].lz, &p[i].rx, &p[i].ry, &p[i].rz); z[m++] = p[i].lz; z[m++] = p[i].rz; } sort(z, z + m); int km = unique(z, z + m) - z; long long ans = 0; for(int i = 0; i < km - 1; i++) { memset(sum, 0, sizeof(sum)); memset(sum2, 0, sizeof(sum2)); memset(sum3, 0, sizeof(sum3)); memset(cnt, 0, sizeof(cnt)); m = 0; for(int j = 1; j <= n; j++) if(p[j].lz <= z[i] && p[j].rz > z[i]) { x[m] = p[j].lx; seg[m++] = Seg(p[j].lx, p[j].rx, p[j].ly, 1); x[m] = p[j].rx; seg[m++] = Seg(p[j].lx, p[j].rx, p[j].ry, -1); } sort(x, x + m); sort(seg, seg + m); int kx = unique(x, x + m) - x; for(int j = 0; j < m - 1; j++) { int l = bin(0, kx - 1, seg[j].l); int r = bin(0, kx - 1, seg[j].r) - 1; if(l <= r) update(l, r, seg[j].s, 0, kx - 1, 1); ans += (long long)sum3[1] * (long long)(seg[j + 1].h - seg[j].h) * (long long)(z[i + 1] - z[i]); } } printf("Case %d: %I64d\n", ++cas, ans); } return 0;}
- POJ 3642 长方体体积并 线段树 扫描线
- HDU 3642 Get The Treasury (线段树扫描线进阶--求长方体重叠3次或以上的体积)
- hdu 3642 求长方体的体积交 (线段树 +离散化+扫描线)(重点!模板!)
- hdu 3255 Farming(线段树求长方体体积并)
- 线段树扫描线(体积并)hdu3642
- HDU3255 Farming(线段树+扫描线+体积并)
- poj 2944 求长方体的体积并
- HDU 3642 Get The Treasury(体积并+覆盖三次+线段树+扫描线)
- hdu3642 线段树长方体体积交
- hdu3255 线段树扫描线求体积
- 【HDU 3642 求长方体的体积并
- hdu3642-Get The Treasury 线段树+扫描线+离散化 求三维体积并
- hdu 3642 Get The Treasury 扫描线求长方体体积交
- poj 1177 经典线段树+扫描线就周长并
- 【线段树 + 扫描线】poj 1177 pictures 矩形周长并
- [poj 1151] Atlantis:扫描线+线段树求面积并
- hdu3255 线段树体积并
- 线段树体积并hdu3255
- 性能提升----禁止servlet和JSP 自动重载(auto-reloading)
- 华为面试笔试题集锦
- 使用Java开发需要关注的那些事儿
- 使用apache的ZipOutputStream进行zip(rar等压缩文件)的文件压缩
- 部署PHP+Apache+MySQL在Windows实战之例
- POJ 3642 长方体体积并 线段树 扫描线
- 初探 HGE Core Functions 层4
- 性能提升----不要滥用HttpSession
- ORA-01219:数据库未打开:仅允许在固定表/视图中查询” 解决办法
- 青春划过指尖
- called unimplemented opengl es api
- Mangos源码分析
- C/C++头文件一览
- 网站突然打不开,解决办法