HDU 3642 Get The Treasury[离散化 + 扫描线 + 线段树]

http://acm.hdu.edu.cn/showproblem.php?pid=3642
给空间中n个立方体,求被这些立方体覆盖过至少3次的区域的体积。
数据范围: |x|106,|y|106,|z|500,1n1000 ,所有坐标都是整数

z坐标范围才1000,直接枚举一下。相当于将这些立方体切成一层层的,每层厚度为1,分别求出每一层至少被覆盖3次的区域的面积即可。也就是对每一层z,找出包含这层的立方体,将它们的xy坐标抽出来,再用平面求被覆盖多次的面积的方法求解,(here)

#include<bits/stdc++.h>
using  namespace std;

typedef long long int64;
#define debug(x) cout<<"debug  "<<x<<endl;
#define rep(i,f,t) for(int i = (f),_end = (t); i <= _end; ++i)
#define clr(c,x) memset(c,x,sizeof(c));

#define MID int mid = (L+R)>>1;
#define CHD int lc = node<<1,rc = node<<1|1;

struct Node{
    int z1,z2,x1,x2,y1,y2;
    Node(int z1,int z2,int x1,int y1,int x2,int y2)
        :z1(z1),z2(z2),x1(x1),x2(x2),y1(y1),y2(y2){}
};
struct Node2{
    int x,y1,y2;
    int flag;
    Node2(int x,int y1,int y2,int f)
        :x(x),y1(y1),y2(y2),flag(f){}
    bool operator< (const Node2 &n2) const{ 
        if(x==n2.x)return flag==1 && n2.flag==-1;
        return x < n2.x;
    }
};
vector<int> vs;
vector<Node> cube;
vector<Node2> line;

const int maxn = 2002<<2;
struct sgt{
    int cov[maxn];
    int64 sum[maxn][4];
    void init(){
        clr(cov,0);
        clr(sum,0);
    }
    void maintain(int node,int L,int R){
        int tot = vs[R]-vs[L-1];
        clr(sum[node], 0);

        rep(i,1,min(3,cov[node]))sum[node][i] = tot;
        if(L==R)return;
        CHD;
        rep(i,cov[node]+1,3){
            sum[node][i] = sum[lc][i-cov[node]]+sum[rc][i-cov[node]];
        }
    }
    double query(){
        return sum[1][3];
    }
    void update(int from,int to,int val,int node,int L,int R){
        if(from <= L && R <= to){
            cov[node] += val;
        }else{
            MID;CHD;
            if(from <= mid)update(from,to,val,lc,L,mid);
            if(to > mid) update(from,to,val,rc,mid+1,R);
        }
        maintain(node,L,R);
    }
}tree;

void pre(){
    sort(vs.begin(),vs.end());
    vs.erase(unique(vs.begin(),vs.end()),vs.end());
    rep(i,0,cube.size()-1){
        cube[i].y1 = lower_bound(vs.begin(),vs.end(),cube[i].y1) - vs.begin();
        cube[i].y2 = lower_bound(vs.begin(),vs.end(),cube[i].y2) - vs.begin();
    }
}

int64 solve(int z){
    line.clear();
    tree.init();
    rep(i,0,cube.size()-1){
        if(cube[i].z1>z || cube[i].z2<=z)continue;
        line.push_back(Node2(cube[i].x1,cube[i].y1,cube[i].y2,1));
        line.push_back(Node2(cube[i].x2,cube[i].y1,cube[i].y2,-1));
    }
    sort(line.begin(),line.end());
    int64 ans = 0;
    int x = line[0].x;
    rep(i,0,line.size()-1){
        int64 len = tree.query();
        ans += len*(line[i].x-x);
        x = line[i].x;
        tree.update(line[i].y1+1,line[i].y2,line[i].flag,1,1,vs.size()-1);
    }
    return ans;
}
int main(){
    int n;
    int casn;
    scanf("%d",&casn);
    rep(cas,1,casn){
        cube.clear();
        vs.clear();
        scanf("%d",&n);
        int from = 505,to = -1;
        rep(i,1,n){
            int x1,y1,x2,y2,z1,z2;
            scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
            vs.push_back(y1);
            vs.push_back(y2);
            cube.push_back(Node(z1,z2,x1,y1,x2,y2));
            from = min(from,z1);
            to = max(to,z2);
        }
        pre();
        int64 ans = 0;
        rep(z2,from,to){
            int64 res = solve(z2);
            ans += res;
        }
        printf("Case %d: %lld\n",cas,ans);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2015-05-01 01:19  DSChan  阅读(117)  评论(0编辑  收藏  举报