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离散化之 ...
随机推荐
- [转载]--类unix系统如何初始化shell
Shell的配置文件 当我们在linux中打开一个shell的时候,系统会读取相关的配置文件来初始化shell(其他unix-like OS也一样).配置文件包括以下这些: 1. 全局配置(对所有用户 ...
- uva 11538 Chess Queen<计数>
链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&am ...
- 最大似然估计(MLE)和最大后验概率(MAP)
最大似然估计: 最大似然估计提供了一种给定观察数据来评估模型参数的方法,即:“模型已定,参数未知”.简单而言,假设我们要统计全国人口的身高,首先假设这个身高服从服从正态分布,但是该分布的均值与方差未知 ...
- viewPager+Handler+Timer简单实现广告轮播效果
基本思想是在Avtivity中放一个ViewPager,然后通过监听去实现联动效果,代码理由详细的解释,我就不说了. MainActivity.java package com.example.adm ...
- R Tools for Visual Studio
https://www.visualstudio.com/en-us/features/rtvs-vs.aspx https://www.microsoft.com/en-us/cloud-platf ...
- TFS(Taobao File System)安装方法
文章目录: 一.TFS(Taobao File System)安装方法 二.TFS(Taobao File System)配置dataServer.分区.挂载数据盘 三.TFS(Taobao File ...
- iOS 取得单张系统图片
这里主要用到了UIImagePickerController 不多废话,直接上代码 // // RootViewController.m // GetImageFromPhotoAlbum // // ...
- 带搜索框的下拉框chosen.jQury.js
下载所需js,css png资源 <link href="chosen.css" rel="stylesheet" type="text ...
- c 计算 语句 执行 时间
当然,你也可以用clock函数来计算你的机器运行一个循环或者处理其它事件到底花了多少时间: #include “stdio.h” #include “stdlib.h” #include “tim ...
- 转载:js动态获取图片长宽尺寸(兼容所有浏览器,速度极快)
转自:http://blog.phpdr.net/js-get-image-size.html lightbox类效果为了让图片居中显示而使用预加载,需要等待完全加载完毕才能显示,体验不佳(如fili ...