不得不说,这是一题很经典的体积并。。

然而还是debug了2个多小时...

首先思路:按z的大小排序。

然后相当于扫描面一样,,从体积的最下方向上方扫描,遇到这个面

就将相应的两条线增加到set中,或者从set中删除,然后再对set中的全部边,求一次面积并

因为最后求出来的是至少有3个体积叠加的部分的体积。

所以须要维护3个节点,然后push_up会略微啰嗦一点...

刚開始在set插入线段和删除线段的时候。搞错了线段所在面的编号,。然后一直例子都过不去也是醉了...

总的来说代码比較冗长须要足够细心才干敲对..

#include<map>
#include<set>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional> using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define root 1,rear-1,1 int const MX = 4e3 + 5; struct Side {
int z, x1, y1, x2, y2, d, id;
bool operator<(const Side &b)const {
if(z == b.z) return d < b.d;
return z < b.z;
}
Side() {}
Side(int _z, int _id, int _x1, int _y1, int _x2, int _y2, int _d) {
z = _z; x1 = _x1; y1 = _y1; x2 = _x2; y2 = _y2; d = _d; id = _id;
}
} A[MX]; struct Line {
int y, x1, x2, d, id;
bool operator<(const Line &b)const {
if(y == b.y) {
if(d == b.d) return id < b.id;
return d < b.d;
}
return y < b.y;
}
Line() {}
Line(int _y, int _id, int _d, int _x1, int _x2) {
y = _y; x1 = _x1; x2 = _x2; d = _d; id = _id;
}
}; int X[MX], rear;
int S1[MX << 2], S2[MX << 2], S3[MX << 2], cnt[MX << 2];
set<Line>work; int BS(int x) {
int L = 1, R = rear, m;
while(L <= R) {
m = (L + R) >> 1;
if(X[m] == x) return m;
if(X[m] > x) R = m - 1;
else L = m + 1;
}
return -1;
} void push_up(int l, int r, int rt) {
if(cnt[rt]) {
S1[rt] = X[r + 1] - X[l];
if(cnt[rt] == 1) {
S2[rt] = S1[rt << 1] + S1[rt << 1 | 1];
S3[rt] = S2[rt << 1] + S2[rt << 1 | 1];
} else {
S2[rt] = X[r + 1] - X[l];
if(cnt[rt] == 2) {
S3[rt] = S1[rt << 1] + S1[rt << 1 | 1];
} else {
S3[rt] = X[r + 1] - X[l];
}
}
} else if(l == r) S1[rt] = S2[rt] = S3[rt] = 0;
else {
S1[rt] = S1[rt << 1] + S1[rt << 1 | 1];
S2[rt] = S2[rt << 1] + S2[rt << 1 | 1];
S3[rt] = S3[rt << 1] + S3[rt << 1 | 1];
}
} void update(int L, int R, int d, int l, int r, int rt) {
if(L <= l && r <= R) {
cnt[rt] += d;
push_up(l, r, rt);
return;
} int m = (l + r) >> 1;
if(L <= m) update(L, R, d, lson);
if(R > m) update(L, R, d, rson);
push_up(l, r, rt);
} LL solve() {
memset(S1, 0, sizeof(S1));
memset(S2, 0, sizeof(S2));
memset(cnt, 0, sizeof(cnt)); LL ans = 0;
int last = 0;
for(set<Line>::iterator it = work.begin(); it != work.end(); it++) {
ans += (LL)(it->y - last) * S3[1];
update(BS(it->x1), BS(it->x2) - 1, it->d, root);
last = it->y;
}
return ans;
} int main() {
//freopen("input.txt", "r", stdin);
int T, n, ansk = 0;
scanf("%d", &T);
while(T--) {
rear = 0;
work.clear(); scanf("%d", &n);
for(int i = 1; i <= n; i++) {
int x1, y1, z1, x2, y2, z2;
scanf("%d%d%d%d%d%d", &x1, &y1, &z1, &x2, &y2, &z2);
A[i] = Side(z1, i, x1, y1, x2, y2, 1);
A[i + n] = Side(z2, i, x1, y1, x2, y2, -1);
X[++rear] = x1; X[++rear] = x2;
}
sort(A + 1, A + 1 + 2 * n);
sort(X + 1, X + 1 + rear);
rear = unique(X + 1, X + 1 + rear) - X - 1; LL ans = 0;
int last = 0;
printf("Case %d: ", ++ansk);
for(int i = 1; i <= 2 * n; i++) {
ans += (LL)(A[i].z - last) * solve(); if(A[i].d > 0) {
work.insert(Line(A[i].y1, A[i].id, 1, A[i].x1, A[i].x2));
work.insert(Line(A[i].y2, A[i].id, -1, A[i].x1, A[i].x2));
} else {
work.erase(Line(A[i].y1, A[i].id, 1, A[i].x1, A[i].x2));
work.erase(Line(A[i].y2, A[i].id, -1, A[i].x1, A[i].x2));
}
last = A[i].z;
}
printf("%I64d\n", ans);
}
return 0;
}

线段树 hdu3642 Get The Treasury的更多相关文章

  1. HDU3642 Get The Treasury —— 求矩形交体积 线段树 + 扫描线 + 离散化

    题目链接:https://vjudge.net/problem/HDU-3642 Jack knows that there is a great underground treasury in a ...

  2. hdu3642 Get The Treasury 线段树--扫描线

    Jack knows that there is a great underground treasury in a secret region. And he has a special devic ...

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

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Others) Memory L ...

  4. HDU 3642 Get The Treasury 线段树+分层扫描线

    http://www.acmerblog.com/hdu-3642-get-the-treasury-6603.html 学习:三维就是把竖坐标离散化分层,每一层进行线段树二维面积并就好了

  5. HDU 3642 Get The Treasury ( 线段树 求长方体体积并 )

    求覆盖三次及其以上的长方体体积并. 这题跟 http://wenku.baidu.com/view/d6f309eb81c758f5f61f6722.html 这里讲的长方体体积并并不一样. 因为本题 ...

  6. [转载]完全版线段树 by notonlysuccess大牛

    原文出处:http://www.notonlysuccess.com/ (好像现在这个博客已经挂掉了,在网上找到的全部都是转载) 今天在清北学堂听课,听到了一些很令人吃惊的消息.至于这消息具体是啥,等 ...

  7. 【转】线段树完全版~by NotOnlySuccess

    线段树完全版  ~by NotOnlySuccess 很早前写的那篇线段树专辑至今一直是本博客阅读点击量最大的一片文章,当时觉得挺自豪的,还去pku打广告,但是现在我自己都不太好意思去看那篇文章了,觉 ...

  8. 《完全版线段树》——notonlysuccess

    转载自:NotOnlySuccess的博客 [完全版]线段树 很早前写的那篇线段树专辑至今一直是本博客阅读点击量最大的一片文章,当时觉得挺自豪的,还去pku打广告,但是现在我自己都不太好意思去看那篇文 ...

  9. 【转】 线段树完全版 ~by NotOnlySuccess

    载自:NotOnlySuccess的博客 [完全版]线段树 很早前写的那篇线段树专辑至今一直是本博客阅读点击量最大的一片文章,当时觉得挺自豪的,还去pku打广告,但是现在我自己都不太好意思去看那篇文章 ...

随机推荐

  1. 【转】Android ClearEditText:输入用户名、密码错误时整体删除及输入为空时候晃动提示

    1 package com.lixu.clearedittext; 2 3 4 import android.app.Activity; 5 import android.os.Bundle; 6 i ...

  2. MyEclipse for mac 快捷键

    原文出处:http://blog.csdn.net/ray_seu/article/details/17384463 一直比较欣赏myeclipse的快捷键,网上搜索了一圈,发现windows平台下面 ...

  3. 共用体 union

    共用体是一种数据格式,能够存储不同的数据类型,但只能同时存储其中的一种类型. union one4all { int int_val; double double_val; long long_val ...

  4. pc端如何引用日期插件

    页面的html部分 <li> <span>出生日期</span> <input type="text" placeholder=" ...

  5. HTML5按键打开摄像头和拍照

    HTML5实现按键打开摄像头和拍照 步骤: 1.创建一个打开摄像头按钮的标签.video标签.拍照的按钮标签.画布 2.实现打开摄像头的功能 3.实现拍照功能   具体实现代码: <!DOCTY ...

  6. HDU-4310 Hero 贪心问题

    题目链接:https://cn.vjudge.net/problem/HDU-4310 题意 打dota,队友太菜,局势变成1vN.还好你开了挂,hp无限大(攻击却只有一点每秒-_-). 但是你并不想 ...

  7. caioj 1081 动态规划入门(非常规DP5:观光游览)

    这道题和前面的分组的题有点像 就是枚举最后一组的长度. 然后组数可以在第一层循环也可以在第二层循环 我自己的话就统一一下在第一层循环吧 然后这道题题意我一直没理解清楚,浪费了很多时间,写复杂了 同时初 ...

  8. unity调用Android的两种方式:其二,调用aar包

    上一篇我们讲了unity如何调用jar包 http://www.cnblogs.com/Jason-c/p/6743224.html, 现在我们介绍一下怎么生成aar包和unity怎么调用aar 一. ...

  9. Android 五大存储方式具体解释

    SharedPreferences与Editor SharedPreferences保存的数据仅仅要是类似于配置信息格式的数据.因此它保存的数据主要是简单的key-value对形式.以下关系图 上图全 ...

  10. 第六课 Struts的视图组件

    Struts框架的视图负责为客户提供动态网页内容. Struts的视图主要由JSP网页构成.此外还包含客户化的标签和ActionForm Bean.这些组件提供了 对国际化.接收用户输入的表单数据.表 ...