HDU 3642 Get The Treasury (线段树扫描线,求体积并)
参考链接 : http://blog.csdn.net/zxy_snow/article/details/6870127
题意:给你n个立方体,求覆盖三次以上(包括三次)的区域的体积
思路:先将z坐标离散后,然后一层一层地开始扫描,计算该层中覆盖>=3次的面积,这个就同二维扫描一样,然后再用面积乘以这层的高度,
即得到该层覆盖>=3次的体积,所有层的体积加起来,即为所求。
对于每一层,只有当该层区域在扫描的线的z1,z2范围中,才将该线条插入。
其它操作就同POJ 1151 Atlantis 求矩形的面积并一样。
这里要注意的是,如果扫描的时候,是用单点更新,那么就会TLE。
后来看了网上别人的区间更新的代码,这才A了。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#define lson rt<<1,L,mid
#define rson rt<<1|1,mid,R
/*
AC
参考链接
http://blog.csdn.net/zxy_snow/article/details/6870127 题意:给你n个立方体,求覆盖三次以上(包括三次)的区域的体积 思路:先将z坐标离散后,然后一层一层地开始扫描,计算该层中覆盖>=3次的面积,这个就同二维扫描一样,然后再用面积乘以这层的高度,
即得到该层覆盖>=3次的体积,所有层的体积加起来,即为所求。
对于每一层,只有当该层区域在扫描的线的z1,z2范围中,才将该线条插入。
其它操作就同POJ 1151 Atlantis 求矩形的面积并一样。 这里要注意的是,如果扫描的时候,是用单点更新,那么就会TLE。
后来看了网上别人的区间更新代码,这才A了。
*/
using namespace std;
const int maxn=;
int n;
int xval[maxn*],zval[maxn*]; //存储x和z出现的所有值
int idx,idz; //xval和zval存储的数的个数
int hashx[maxn*],hashz[maxn*]; //用于离散化
int hx,hz; //x和z离散后的个数
long long ans; struct Line{
//l r:线条的横坐标左端点和右端点;y:纵坐标值
//z1 z2:线条所处的z坐标范围
int l,r,y,z1,z2;
int tp; //标记,tp=1表示矩形的下边,tp=-1表示矩形的上边
bool operator<(const Line tmp)const{
return y<tmp.y;
}
}line[maxn*]; struct Node{
int cnt; //该区间被覆盖的次数
/*
once:该区间中被覆盖一次的线段长度
twice:该区间中被覆盖两次的线段长度
len:该区间中被覆盖>=三次的线段长度
*/
long long once,twice,len;
}tree[maxn<<]; //二分搜索x坐标对应的离散值
int binarySearchx(int m){
int l=,r=hx+,mid;
while(r-l>){
mid=(l+r)>>;
if(hashx[mid]<=m)
l=mid;
else
r=mid;
}
return l;
} void build(int rt,int L,int R){
tree[rt].cnt=tree[rt].len=tree[rt].twice=tree[rt].once=;
if(L+==R)
return;
int mid=(L+R)>>;
build(lson);
build(rson);
}
/*
还是网上看了大牛们的代码,用区间查询,才AC
原本自己就直接单点更新,导致TLE。。。
*/
void pushUp(int rt,int L,int R){
if(tree[rt].cnt>=){
tree[rt].once=tree[rt].twice=;
tree[rt].len=hashx[R]-hashx[L];
}
else if(tree[rt].cnt==){
if(L+==R){
tree[rt].once=tree[rt].len=;
tree[rt].twice=hashx[R]-hashx[L];
}
else{
tree[rt].once=;
tree[rt].len=tree[rt<<].len+tree[rt<<|].len+tree[rt<<].twice+tree[rt<<|].twice
+tree[rt<<].once+tree[rt<<|].once;
tree[rt].twice=hashx[R]-hashx[L]-tree[rt].len;
}
}
else if(tree[rt].cnt==){
if(L+==R){
tree[rt].once=hashx[R]-hashx[L];
tree[rt].twice=tree[rt].len=;
}
else{
tree[rt].len=tree[rt<<].len+tree[rt<<|].len+tree[rt<<].twice+tree[rt<<|].twice;
tree[rt].twice=tree[rt<<].once+tree[rt<<|].once;
tree[rt].once=hashx[R]-hashx[L]-tree[rt].len-tree[rt].twice;
}
}
else{
if(L+==R){
tree[rt].len=tree[rt].once=tree[rt].twice=;
}
else{
tree[rt].len=tree[rt<<].len+tree[rt<<|].len;
tree[rt].twice=tree[rt<<].twice+tree[rt<<|].twice;
tree[rt].once=tree[rt<<].once+tree[rt<<|].once;
}
}
} void update(int rt,int L,int R,int l,int r,int c){
if(l<=L&&R<=r){
tree[rt].cnt+=c;
pushUp(rt,L,R);
return;
}
int mid=(L+R)>>;
if(r<=mid)
update(lson,l,r,c);
else if(l>=mid)
update(rson,l,r,c);
else{
update(lson,l,mid,c);
update(rson,mid,r,c);
}
pushUp(rt,L,R);
}
int main()
{
int t;
int x1,y1,z1,x2,y2,z2;
scanf("%d",&t);
for(int q=;q<=t;q++){
scanf("%d",&n);
idx=idz=;
for(int i=;i<=n;i++){
scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
line[*i-].l=x1;line[*i-].r=x2;line[*i-].y=y1;line[*i-].z1=z1;line[*i-].z2=z2;line[*i-].tp=;
line[*i].l=x1;line[*i].r=x2;line[*i].y=y2;line[*i].z1=z1;line[*i].z2=z2;line[*i].tp=-;
xval[++idx]=x1;
xval[++idx]=x2;
zval[++idz]=z1;
zval[++idz]=z2;
}
n=n*;
sort(line+,line+n+);
sort(xval+,xval+idx+);
sort(zval+,zval+idz+);
hx=hz=;
//将x坐标值离散化
hashx[++hx]=xval[];
for(int i=;i<=idx;i++){
if(xval[i]!=xval[i-])
hashx[++hx]=xval[i];
}
//将y坐标值离散化
hashz[++hz]=zval[];
for(int i=;i<=idz;i++){
if(zval[i]!=zval[i-])
hashz[++hz]=zval[i];
} ans=;
int minz,maxz;
int a,b;
//一层一层地扫描
for(int i=;i<hz;i++){
//minz和maxz表示该层所处的范围
minz=hashz[i];
maxz=hashz[i+];
build(,,hx);
long long s=; //该层被覆盖>=3的面积
int last=; //记录上一次扫描线的编号
for(int j=;j<=n;j++){
if(line[j].z1<=minz && maxz<=line[j].z2){
s+=tree[].len*(line[j].y-line[last].y);
last=j;
a=binarySearchx(line[j].l);
b=binarySearchx(line[j].r);
update(,,hx,a,b,line[j].tp);
}
}
ans+=s*(maxz-minz);
}
printf("Case %d: %I64d\n",q,ans);
}
return ;
}
后来这道题自己又做了一遍,基本上和之前的差不多,只不过离散化的时候就在原来数组的基础上进行
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define lson rt<<1,L,mid
#define rson rt<<1|1,mid+1,R
using namespace std;
const int maxn=+;
int n,m;
int cntx,idx;
int cntz,idz;
int hashx[maxn<<];
int hashz[maxn<<]; struct Line{
int y,l,r;
int tp;
int z1,z2;
bool operator<(const Line tmp)const{
return y<tmp.y;
}
}line[maxn<<]; struct Node{
int cnt;
int len[];
}tree[maxn<<]; void build(int rt,int L,int R){
tree[rt].cnt=;
tree[rt].len[]=tree[rt].len[]=tree[rt].len[]=;
if(L==R)
return;
int mid=(L+R)>>;
build(lson);
build(rson);
} void pushUp(int rt,int L,int R){
//别忘了考虑叶子节点的情况
if(tree[rt].cnt==){
if(L==R){
tree[rt].len[]=tree[rt].len[]=tree[rt].len[]=;
}
else{
tree[rt].len[]=tree[rt<<].len[]+tree[rt<<|].len[];
tree[rt].len[]=tree[rt<<].len[]+tree[rt<<|].len[];
tree[rt].len[]=tree[rt<<].len[]+tree[rt<<|].len[];
}
}
else if(tree[rt].cnt==){
if(L==R){
tree[rt].len[]=hashx[R+]-hashx[L];
tree[rt].len[]=tree[rt].len[]=;
}
else{
tree[rt].len[]=tree[rt<<].len[]+tree[rt<<|].len[]+tree[rt<<].len[]+tree[rt<<|].len[];
tree[rt].len[]=tree[rt<<].len[]+tree[rt<<|].len[];
tree[rt].len[]=hashx[R+]-hashx[L]-tree[rt].len[]-tree[rt].len[];
}
}
else if(tree[rt].cnt==){
if(L==R){
tree[rt].len[]=hashx[R+]-hashx[L];
tree[rt].len[]=tree[rt].len[]=;
}
else{
tree[rt].len[]=;
tree[rt].len[]=tree[rt<<].len[]+tree[rt<<].len[]+tree[rt<<].len[]
+tree[rt<<|].len[]+tree[rt<<|].len[]+tree[rt<<|].len[];
tree[rt].len[]=hashx[R+]-hashx[L]-tree[rt].len[];
}
}
else{
tree[rt].len[]=tree[rt].len[]=;
tree[rt].len[]=hashx[R+]-hashx[L];
}
}
void update(int rt,int L,int R,int l,int r,int val){
if(l<=L&&R<=r){
tree[rt].cnt+=val;
pushUp(rt,L,R);
return;
}
int mid=(L+R)>>;
if(l<=mid)
update(lson,l,r,val);
if(r>mid)
update(rson,l,r,val);
pushUp(rt,L,R);
}
int binarySearch(int x){
int l=,r=idx+,mid;
while(r-l>){
mid=(l+r)>>;
if(hashx[mid]<=x)
l=mid;
else
r=mid;
}
return l;
}
int main()
{
int t;
int x1,y1,z1,x2,y2,z2;
scanf("%d",&t);
for(int q=;q<=t;q++){
scanf("%d",&n);
cntx=cntz=;
for(int i=;i<=n;i++){
scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
line[*i-].y=y1;line[*i-].l=x1;line[*i-].r=x2;
line[*i-].z1=z1;line[*i-].z2=z2;line[*i-].tp=;
line[*i].y=y2;line[*i].l=x1;line[*i].r=x2;
line[*i].z1=z1;line[*i].z2=z2;line[*i].tp=-;
hashx[cntx++]=x1;
hashx[cntx++]=x2;
hashz[cntz++]=z1;
hashz[cntz++]=z2;
}
n=n*;
sort(hashx+,hashx+cntx);
sort(hashz+,hashz+cntz);
idx=;
for(int i=;i<cntx;i++){
if(hashx[i]!=hashx[i-]){
hashx[++idx]=hashx[i];
}
}
idz=;
for(int i=;i<cntz;i++){
if(hashz[i]!=hashz[i-])
hashz[++idz]=hashz[i];
}
sort(line+,line+n+); long long ans=;
for(int i=;i<idz;i++){
long long area=;
int last=;
build(,,idx);
for(int j=;j<=n;j++){
if(line[j].z1<=hashz[i] && hashz[i+]<=line[j].z2){
//这里乘积可能会爆int,所以要转化成long long,或者将tree[1].len定义成long long
area+=(long long)tree[].len[]*(line[j].y-line[last].y);
int a=binarySearch(line[j].l);
int b=binarySearch(line[j].r)-;
update(,,idx,a,b,line[j].tp);
last=j;
}
}
ans+=area*(hashz[i+]-hashz[i]);
}
printf("Case %d: %I64d\n",q,ans);
}
return ;
}
HDU 3642 Get The Treasury (线段树扫描线,求体积并)的更多相关文章
- HDU 3642 Get The Treasury 线段树+分层扫描线
http://www.acmerblog.com/hdu-3642-get-the-treasury-6603.html 学习:三维就是把竖坐标离散化分层,每一层进行线段树二维面积并就好了
- HDU 3642 Get The Treasury ( 线段树 求长方体体积并 )
求覆盖三次及其以上的长方体体积并. 这题跟 http://wenku.baidu.com/view/d6f309eb81c758f5f61f6722.html 这里讲的长方体体积并并不一样. 因为本题 ...
- hdu3642 Get The Treasury 线段树--扫描线
Jack knows that there is a great underground treasury in a secret region. And he has a special devic ...
- HDU 1264 Counting Squares (线段树-扫描线-矩形面积并)
版权声明:欢迎关注我的博客.本文为博主[炒饭君]原创文章,未经博主同意不得转载 https://blog.csdn.net/a1061747415/article/details/25471349 P ...
- HDU 4419 Colourful Rectangle --离散化+线段树扫描线
题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何 ...
- hdu3255 线段树扫描线求体积
题意: 给你n个矩形,每个矩形上都有一个权值(该矩形单位面积的价值),矩形之间可能重叠,重叠部分的权值按照最大的算,最后问这n个矩形组成的图形的最大价值. 思路: 线段树扫描线 ...
- HDU 1255 覆盖的面积 (线段树+扫描线+离散化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 题意很清楚,就是让你求矩阵之间叠加层数大于1的矩形块的面积和. 因为n只有1000,所以我离散化 ...
- HDU 4419 Colourful Rectangle(线段树+扫描线)
题目链接 主要是pushup的代码,其他和区间更新+扫描线差不多. 那个区间如果要再刷一层x,那么sum[x][rt] = que[r+1] - que[l];但是如果原本有颜色为i,颜色将会变成i| ...
- hdu 3642 Get The Treasury (三维的扫描线)
题目大意: 给出N个立方体. 求一个三维空间中被包围三次的空间的体积之和. 思路分析: 发现Z的范围非常小.那么我们能够枚举Z轴,然后对 x y做扫描线. 并且不用枚举全部的Z ,仅仅须要将Z离散化之 ...
随机推荐
- JavaScript 组件化开发之路(一)
*:first-child{margin-top: 0 !important}.markdown-body>*:last-child{margin-bottom: 0 !important}.m ...
- C 的 一些写法格式 交流
好久以前刚开始学习前辈们的代码的时候,发现好多代码感到好奇怪. 1)代码看不懂 2)代码格式看不懂 网上也没见同学们分享.当自己代码写多了,也渐渐的理解为什么要这样写了. 说主题之前 还是 说一些 题 ...
- debian完整部署 Nginx + uWSGI + Django
手工部署一个Django服务器真心不容易,需要安装很多东西.从头开始搭建服务器,主要是为了梳理一下后续开发中一般为碰到的平台部署.对后续问题的解决有一定帮助. 通常部署有2中方式: 一种是使用现成提供 ...
- MAC 重置MySQL root 密码
重置MySQL root 密码:当忘记密码,或者想要强行重置 MySQL 密码的时候,可以像下面这样: 1.停止 MySQL 服务 sudo /usr/local/mysql/support-file ...
- Oracle redo 日志切换时间频率
DB: 11.2.0.3.0 查看Oracle的redo日志切换频率 两条SQL,原理是一样的,第二个用到了统计函数 时间单位:分钟 方法一. select * from v$log a where ...
- SQL 跟踪方法相关介绍
oracle sql跟踪方法:1.sql_trace打开跟踪:alter session set sql_trace=true;为跟踪文件做标记:alter session set tracefile ...
- Spring框架中的IOC和DI的区别
上次面试被问到IOC和DI的区别时,没怎么在意,昨天又被问到,感觉有点可惜.今晚总算抽点时间,查看了spring官方文档.发现,IoC更像是一种思想,DI是一种行为.为了降低程序的耦合度,利用spri ...
- [转]va_start和va_end使用详解
转载地址:http://www.cnblogs.com/hanyonglu/archive/2011/05/07/2039916.html 本文主要介绍va_start和va_end的使用及原理. ...
- Android编程: 界面组成、事件监听器
学习知识:界面组成.事件监听器 ====界面组成==== 1.用户界面的基本组件叫做View,都是继承android.view.View类,Android里面预定义很多基本的界面组件,比如 Butto ...
- FPGA保留信号的语句
(*synthesis,keep*) (*synthesis,probe_port,keep *) 例:(*synthesis,probe_port,keep *) wire e; 可用于wire型和 ...