hdu3642 Get The Treasury

来源:互联网 发布:mac rar解压软件 编辑:程序博客网 时间:2024/06/05 23:51

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

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

#include<stdio.h>#include<string.h>#include<vector>#include<algorithm>#define LL __int64using 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,Zint 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
原创粉丝点击