poj 2944 求长方体的体积并

来源:互联网 发布:淘宝代销发货怎么联系 编辑:程序博客网 时间:2024/04/28 05:46

有点特殊,每个长方体的底面的左下角都在(0,0 , 0)

所以计算面积的时候就简单很多了。

用线段树,对x坐标建树

rm[rt]:区间最右端y值

mx[rt]:管辖区间内最大的y值

sum[rt]:管辖区间内的总面积

cover[rt]:是否被某个y值完全覆盖

求体积的时候,从下往上不好求

因为如果y大的长方体在下面,y小的在上面,从下往上计算的时候会多算

比如 5 5 5

      1 1 10

两个长方体,在计算5到10的体积时,面积并的和是25,实际上是1

而从上往下求体积就不会出现这种问题

View Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100010;
typedef __int64 lld;
#define max(a,b) a>b?a:b
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int rm[maxn<<2],mx[maxn<<2],cover[maxn<<2];
int sum[maxn<<2];
struct node{
int x,y,z;
bool operator< (const node &cmp) const {
return z>cmp.z;
}
}cube[maxn];
void pushup(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
rm[rt]=rm[rt<<1|1];
mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
}
void make(int l,int r,int rt,int val){
cover[rt]=1;
sum[rt]=val*(r-l+1);
rm[rt]=mx[rt]=val;
}
void pushdown(int l,int r,int rt){
if(cover[rt]){
cover[rt]=0;
int m=(l+r)>>1;
make(lson,mx[rt]);
make(rson,mx[rt]);
}
}
void build(int l,int r,int rt){
rm[rt]=mx[rt]=sum[rt]=cover[rt]=0;
if(l==r) return ;
int m=(l+r)>>1;
build(lson);
build(rson);
}
void update(int L,int R,int val,int l,int r,int rt){
if(rm[rt]>=val) return ;
if(L<=l&&r<=R&&mx[rt]<=val){
make(l,r,rt,val);
return ;
}
pushdown(l,r,rt);
int m=(l+r)>>1;
if(L<=m) update(L,R,val,lson);
if(R>m) update(L,R,val,rson);
pushup(rt);
}
int main(){
int n,m,i,j;
while(scanf("%d%d",&n,&m)!=EOF){
if(n==0&&m==0) break;
build(0,m-1,1);
for(i=0;i<n;i++)scanf("%d%d%d",&cube[i].x,&cube[i].y,&cube[i].z);
sort(cube,cube+n);
cube[n].z=0;
lld vol=0;
for(i=0;i<n;i++){
if(cube[i].x>0) update(0,cube[i].x-1,cube[i].y,0,m-1,1);
vol+=(lld)sum[1]*(cube[i].z-cube[i+1].z);
}
printf("%I64d\n",(lld)m*m*m-vol);
}
}



原创粉丝点击