hdu3642 Get The Treasury

题意:给一些长方体,求这些长方体相交2次以上的体积

思路:在做过两维的之后做这个其实是一样的思路,先把z(第三维)处理了,然后在各个平面上面做扫描线(这里就和两维的一样了)

#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
#define LL __int64
using namespace std;
const int maxn = 1010;
struct haha{int x1,x2,y1,y2,z1,z2;}s[maxn]; ///保存输入
struct node
{
    int x,y1,y2,f;
    node(){}
    node(int xx,int yy1,int yy2,int ff)
    {x=xx,y1=yy1,y2=yy2,f=ff;}
    bool operator<(node a)const
    {
        if(x==a.x) return f < a.f;
        return x < a.x;
    }
}sa[maxn*2];
int Y[maxn*2],Z[maxn*2]; ///离散化坐标Y,Z
int T,n,y,z; 
bool has[maxn]; ///表示这个长方体还在不在计算范围
vector<pair<int,int> >pp[maxn*2]; ///表示各个长方体插入或删除
int cov[maxn<<3],one[maxn<<3],two[maxn<<3],more[maxn<<3]; ///cov表示当前段覆盖,one,two,more表示覆盖1次,2次,多次
void pushup(int rt,int l,int r)
{
    int ls = rt<<1,rs = rt<<1|1;
    if(l==r) ls = 0,rs = 0; ///也可以再把数组开大2倍
    if(cov[rt]==0)
    {
        more[rt] = more[ls] + more[rs];
        two[rt] = two[ls] + two[rs];
        one[rt] = one[ls] + one[rs];
    }
    if(cov[rt]==1)
    {
        more[rt] = two[ls] + two[rs] + more[ls] + more[rs];
        two[rt] = one[ls] + one[rs];
        one[rt] = Y[r+1] - Y[l] - two[rt] - more[rt];
    }
    if(cov[rt]==2)
    {
        more[rt] = one[ls] + one[rs] + two[ls] + two[rs] + more[ls] + more[rs];
        two[rt] = Y[r+1] - Y[l] - more[rt];
        one[rt] = 0;
    }
    if(cov[rt]==3)
    {
        more[rt] = Y[r+1] - Y[l];
        one[rt] = two[rt] = 0;
    }
}
void update(int L,int R,int x,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        cov[rt]+=x;
        pushup(rt,l,r);
        return;
    }
    int m = (l+r)/2;
    if(L<=m) update(L,R,x,l,m,rt<<1);
    if(R>m)  update(L,R,x,m+1,r,rt<<1|1);
    pushup(rt,l,r);
}
LL calc()  ///扫描当前平面
{
    LL res = 0;
    int en = 0;
    for(int i=0;i<n;i++)
        if(has[i])
        {
            int y1 = lower_bound(Y,Y+y,s[i].y1)-Y;
            int y2 = lower_bound(Y,Y+y,s[i].y2)-Y-1;
            sa[en++] = node(s[i].x1,y1,y2,1);
            sa[en++] = node(s[i].x2,y1,y2,-1);
        }
    sort(sa,sa+en);
    memset(cov,0,sizeof(cov));
    memset(one,0,sizeof(one));
    memset(two,0,sizeof(two));
    memset(more,0,sizeof(more));
    for(int i=0;i<en-1;i++)
    {
        update(sa[i].y1,sa[i].y2,sa[i].f,0,y,1);
        res += (LL)more[1]*(sa[i+1].x - sa[i].x);
    }
    return res;
}
int main()
{
    scanf("%d",&T);
    for(int ca=1;ca<=T;ca++)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d%d%d%d%d%d",&s[i].x1,&s[i].y1,&s[i].z1,&s[i].x2,&s[i].y2,&s[i].z2);
            Y[i] = s[i].y1, Y[i+n] = s[i].y2;
            Z[i] = s[i].z1, Z[i+n] = s[i].z2;
            pp[i].clear(), pp[i+n].clear();
            has[i] = 0;
        }
        sort(Z, Z+2*n);
        z = unique(Z, Z+2*n) - Z;
        sort(Y, Y+2*n);
        y = unique(Y, Y+2*n) - Y;
        for(int i=0;i<n;i++)
        {
            int t1 = lower_bound(Z, Z+z, s[i].z1)-Z;
            int t2 = lower_bound(Z, Z+z, s[i].z2)-Z;
            pp[t1].push_back(make_pair(i,1));
            pp[t2].push_back(make_pair(i,-1));
        }
        LL ans = 0;
        for(int i=0;i<z-1;i++) ///分开z个平面来分别做扫描线
        {
            for(int j=0;j<pp[i].size();j++)
            {
                if(pp[i][j].second>0)
                    has[pp[i][j].first]=1;
                else
                    has[pp[i][j].first]=0;
            }
            ans += calc()*(Z[i+1]-Z[i]);
        }
        printf("Case %d: %I64d\n", ca, ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值