参考链接 : 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 (线段树扫描线,求体积并)的更多相关文章

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

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

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

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

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

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

  4. HDU 1264 Counting Squares (线段树-扫描线-矩形面积并)

    版权声明:欢迎关注我的博客.本文为博主[炒饭君]原创文章,未经博主同意不得转载 https://blog.csdn.net/a1061747415/article/details/25471349 P ...

  5. HDU 4419 Colourful Rectangle --离散化+线段树扫描线

    题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何 ...

  6. hdu3255 线段树扫描线求体积

    题意:       给你n个矩形,每个矩形上都有一个权值(该矩形单位面积的价值),矩形之间可能重叠,重叠部分的权值按照最大的算,最后问这n个矩形组成的图形的最大价值. 思路:       线段树扫描线 ...

  7. HDU 1255 覆盖的面积 (线段树+扫描线+离散化)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 题意很清楚,就是让你求矩阵之间叠加层数大于1的矩形块的面积和. 因为n只有1000,所以我离散化 ...

  8. HDU 4419 Colourful Rectangle(线段树+扫描线)

    题目链接 主要是pushup的代码,其他和区间更新+扫描线差不多. 那个区间如果要再刷一层x,那么sum[x][rt] = que[r+1] - que[l];但是如果原本有颜色为i,颜色将会变成i| ...

  9. hdu 3642 Get The Treasury (三维的扫描线)

    题目大意: 给出N个立方体. 求一个三维空间中被包围三次的空间的体积之和. 思路分析: 发现Z的范围非常小.那么我们能够枚举Z轴,然后对 x y做扫描线. 并且不用枚举全部的Z ,仅仅须要将Z离散化之 ...

随机推荐

  1. C扩展 从共享内存shm到memcache外部内存

    引言 - ipc - shm 共享内存 本文会通过案例了解ipc 的共享内存机制使用, 后面会讲解C 如何使用外部内存服务memcached. 好先开始了解 linux 共享内存机制. 推荐先参看下面 ...

  2. C 基于UDP实现一个简易的聊天室

    引言 本文是围绕Linux udp api 构建一个简易的多人聊天室.重点看思路,帮助我们加深 对udp开发中一些api了解.相对而言udp socket开发相比tcp socket开发注意的细节要少 ...

  3. Android SharedPreferences使用以及原理详解

    SharedPreferences的使用非常简单,能够轻松的存放数据和读取数据.SharedPreferences只能保存简单类型的数据,例如,String.int等.一般会将复杂类型的数据转换成Ba ...

  4. 基于perl的网络爬虫

    use Mojo::UserAgent; use Bloom::Filter; use Smart::Comments; use DBI; my $dbname = "bbs_url&quo ...

  5. iOS学习之界面通信

    一.属性传值 在SecondViewController.h里 #import <UIKit/UIKit.h> @interface SecondViewController : UIVi ...

  6. snmp4j 编程

    从www.snmp4j.org下载snmp4j的jar包,用eclipse新建一个java项目.将jar包导入工程(只有一个jar包),开始编程 一个简单的测试程序 //create target / ...

  7. How to insert a character into a NSString

    How do I insert a space to a NSString. I need to add a space at index 5 into: NString * dir = @" ...

  8. Google Volley: How to send a POST request with Json data?

    sonObjectRequest actuallyaccepts JSONObject as body. From http://arnab.ch/blog/2013/08/asynchronous- ...

  9. 软件工程随堂小作业——随机四则运算Ⅱ(C++)

    一.设计思路 设计思路已给出,此处不再赘述. 二.源代码 (1)四则运算2.cpp(源文件) // 四则运算2.cpp : Defines the entry point for the consol ...

  10. ios-仿新浪微博app-第1天UI搭建

    1:不用storyboard 点击工程删除main  ui加载全部手码  >> 在application的代理方法didFinishLaunchingWithOptions中添加代码显示w ...