Get The Treasury【HDU-3642】【扫描线】
题目给出的是N个体积块,问的是有多少体积重叠了3次及以上?
那么就是怎么处理体积这样子的问题了,看到Z的种类不多的时候,就想着从Z离散化的角度去考虑这个问题了,然后就是怎样子去处理面积了,这时候想到每一个Z所代表的这个面对应上的体积,然后把每个面都处理出来看,体积就是在处理X的和,以及求Y、Z的差(差分)来的乘积,所以在处理Z上的时候也有些细节的东西,就是我们要考虑到目前所访问到的这个面积段是否是可以取的,也就是要去判断它的上下Z坐标和目前的区间的上下Z坐标的关系式了。
另外,在处理pushup()的时候,也是需要注意细节,我在这里处理的是"≥times"也就是覆盖次数大于等于1的线段的长、大于等于2的线段的长……
剩下的吧,基本就是写代码上的,细心点,没什么其他的了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 1e3 + ;
int N, X[maxN<<], tot, Z[maxN<<], cnt, lsan_Z, _UP;
struct IOput
{
int lx, ly, lz, rx, ry, rz;
}a[maxN];
struct node
{
int lx, rx, y, val;
node(int a=, int b=, int c=, int d=):lx(a), rx(b), y(c), val(d) {}
}line[maxN<<];
bool cmp(node e1, node e2) { return e1.y < e2.y; }
struct Tree
{
int siz, sum, len1, len2; //求的是"≥times"的数的个数和
void clear() { siz = sum = len1 = len2 = ; }
}t[maxN<<];
inline void buildTree(int rt, int l, int r)
{
t[rt].clear();
if(l == r) return;
int mid = HalF;
buildTree(Lson);
buildTree(Rson);
}
inline void pushup(int rt, int l, int r)
{
if(t[rt].siz >= )
{
t[rt].sum = t[rt].len2 = t[rt].len1 = X[r + ] - X[l];
}
else if(t[rt].siz == )
{
t[rt].sum = t[lsn].len1 + t[rsn].len1;
t[rt].len2 = t[rt].len1 = X[r + ] - X[l];
}
else if(t[rt].siz == )
{
t[rt].sum = t[lsn].len2 + t[rsn].len2;
if(l == r) t[rt].len2 = ; //相等的时候记得清空对应值
else t[rt].len2 = t[lsn].len1 + t[rsn].len1;
t[rt].len1 = X[r + ] - X[l];
}
else if(l == r) t[rt].clear();
else
{
t[rt].sum = t[lsn].sum + t[rsn].sum;
t[rt].len2 = t[lsn].len2 + t[rsn].len2;
t[rt].len1 = t[lsn].len1 + t[rsn].len1;
}
}
inline void update(int rt, int l, int r, int ql, int qr, int val)
{
if(ql <= l && qr >= r)
{
t[rt].siz += val;
pushup(myself);
return;
}
int mid = HalF;
if(qr <= mid) update(QL, val);
else if(ql > mid) update(QR, val);
else { update(QL, val); update(QR, val); }
pushup(myself);
}
inline void init()
{
cnt = ;
}
int main()
{
int T; scanf("%d", &T);
for(int Cas=; Cas<=T; Cas++)
{
scanf("%d", &N);
init();
for(int i=; i<=N; i++)
{
scanf("%d%d%d%d%d%d", &a[i].lx, &a[i].ly, &a[i].lz, &a[i].rx, &a[i].ry, &a[i].rz);
Z[++cnt] = a[i].lz;
Z[++cnt] = a[i].rz;
}
sort(Z + , Z + cnt + );
lsan_Z = (int)(unique(Z + , Z + cnt + ) - Z - );
ll ans = ;
for(int u=; u<lsan_Z; u++)
{
tot = ;
for(int i=; i<=N; i++)
{
if(a[i].lz <= Z[u] && a[i].rz > Z[u]) //不能计算前面已经算过的部分,就是存在头即尾的情况
{
line[++tot] = node(a[i].lx, a[i].rx, a[i].ly, );
X[tot] = a[i].lx;
line[++tot] = node(a[i].lx, a[i].rx, a[i].ry, -);
X[tot] = a[i].rx;
}
}
sort(line + , line + tot + , cmp);
sort(X + , X + tot + );
_UP = (int)(unique(X + , X + tot + ) - X - );
memset(t, , sizeof(t));
for(int i=, l, r; i<tot; i++)
{
l = (int)(lower_bound(X + , X + _UP + , line[i].lx) - X);
r = (int)(lower_bound(X + , X + _UP + , line[i].rx) - X - );
update(, , _UP, l, r, line[i].val);
ans += (ll)(Z[u + ] - Z[u]) * (ll)(line[i + ].y - line[i].y) * (t[].sum);
}
}
printf("Case %d: %lld\n", Cas, ans);
}
return ;
}
/*
1
6
1 0 0 2 2 2
0 1 0 2 2 2
0 0 1 2 2 2
1 0 0 2 2 2
0 1 0 2 2 2
0 0 1 2 2 2
ans = 4
*/
Get The Treasury【HDU-3642】【扫描线】的更多相关文章
- Get The Treasury HDU - 3642(体积扫描线)
给出n个立方体,要你求这些立方体至少被覆盖三次的部分. 先把这个立方体的信息存在来,发现Z的范围不大,z范围是是[-500,500],所以我们可以先离散化,然后枚举Z, 然后对于每一段Z的区域内,在当 ...
- Get The Treasury HDU - 3642(扫描线求三维面积交。。体积交)
题意: ...就是求体积交... 解析: 把每一层z抽出来,计算面积交, 然后加起来即可..! 去看一下 二维面积交的代码 再看看这个三维面积交的代码.. down函数里 你发现了什么规律!!! 参考 ...
- HDU 3642 扫描线(立方体体积并)
Get The Treasury Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- Q - Get The Treasury - HDU 3642 (扫面线求体积)
题意:求被三个或三个以上立方体重合的体积 分析:就是平面面积的加强,不过归根还是一样的,可以把z轴按照从小向大分区间N个,然后可以得到N个平面,用平面重复三次以上的在和高度计算体积. ******** ...
- hdu 3642 Get The Treasury(扫描线)
pid=3642" style="">题目链接:hdu 3642 Get The Treasury 题目大意:三维坐标系,给定若干的长方体,问说有多少位置被覆盖3次 ...
- HDU 3642 - Get The Treasury - [加强版扫描线+线段树]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Others) Memory L ...
- HDU 3642 Get The Treasury (线段树扫描线,求体积并)
参考链接 : http://blog.csdn.net/zxy_snow/article/details/6870127 题意:给你n个立方体,求覆盖三次以上(包括三次)的区域的体积 思路:先将z坐标 ...
- hdu 3642 Get The Treasury (三维的扫描线)
题目大意: 给出N个立方体. 求一个三维空间中被包围三次的空间的体积之和. 思路分析: 发现Z的范围非常小.那么我们能够枚举Z轴,然后对 x y做扫描线. 并且不用枚举全部的Z ,仅仅须要将Z离散化之 ...
- HDU 3642 Get The Treasury (线段树扫描线)
题意:给你一些长方体,问你覆盖三次及以上的体积有多大 首先我们观察x轴y轴一样很大,但是z轴很小,所以我们可以枚举z轴(-500,500),注意我们枚举的是每一段长度为一的z轴的xy轴的面积而不是点. ...
- HDU 3642 Get The Treasury 线段树+分层扫描线
http://www.acmerblog.com/hdu-3642-get-the-treasury-6603.html 学习:三维就是把竖坐标离散化分层,每一层进行线段树二维面积并就好了
随机推荐
- mysql 5.7 事务隔离级别
事务的隔离级别分为:未提交读(read uncommitted).已提交读(read committed).可重复读(repeatable read).串行化(serializable). 未提交读: ...
- .net 异步
原文:https://www.cnblogs.com/wisdomqq/archive/2012/03/26/2412349.html 在说到异步前,先来理一下几个容易混淆的概念,并行.多线程.异步. ...
- 对VS2019进行32位汇编环境配置
1.库文件(很重要) 用我这一份就行:https://www.lanzous.com/i6364hg 2.VS依赖库 打开VS2019,选择桌面向导 配置项目时,选择新项目. 选择生成依赖项 选中ma ...
- 【JAVA】 03-Java中的异常和包的使用
链接: 笔记目录:毕向东Java基础视频教程-笔记 GitHub库:JavaBXD33 目录: <> <> 内容待整理: 异常 异常和错误的发生和区别 异常:java运行期间发 ...
- Solr的学习使用之(三)IKAnalyzer中文分词器的配置
1.为什么要配置? 1.我们知道要使用Solr进行搜索,肯定要对词语进行分词,但是由于Solr的analysis包并没有带支持中文的包或者对中文的分词效果不好,需要自己添加中文分词器:目前呼声较高的是 ...
- MySQL--07 explain用法
目录 MySQL explain用法 一.explain命令应用 二. Extra(扩展) 三.建立索引的原则(规范) 总结: MySQL explain用法 一.explain命令应用 查询数据的方 ...
- java 静态内存图、静态代码块
package java08; /* 静态代码块格式: public class 类名称{ static{ //静态代码块 } } 特点:当第一次执行本类时,静态代码块执行唯一的一次 * */ pub ...
- Java EE模式和MVC
Java EE模式 什么是模式? 开发过程中总结出来的约定俗成的"套路". Java EE经历的模式 model1模式 技术组成:JSP+JavaBean model1的弊端:随着 ...
- Python repr, str, eval 使用小记 及 str 和 repr的区别
>>> s = '1+2'>>> x = eval(s) #把引号剥离一次,就变成了运算1+2>>> x3>>> ss = st ...
- python每日练习10题2
163.一个字典 key 是人名.value 是年龄,找出其中年龄 最大的人 d = {"张三":25,"李四":30,"王五":80,&q ...