HDU 3642 Get The Treasury(离散化+线段树:扫描线)

来源:互联网 发布:mac图标放在桌面 编辑:程序博客网 时间:2024/06/14 08:49

HDU 3642 Get The Treasury(离散化+线段树:扫描线)

http://acm.hdu.edu.cn/showproblem.php?pid=3642

分析:

       本题要求的是重叠3次及以上的立方体体积,由于Z轴范围很小,可以枚举Z轴,然后固定了Z轴之后,就是求二维矩形的面积交>=3次的总面积了.其实Z轴就算很大也可以求,只需要把Z轴离散化即可.

比如Z轴从小到大出现了1,10,100,1000共四个值.然后假设当前考虑Z==1时,那么只需要把那些包括了[1,10]区间的立方体加入到二维矩形球面积的线段树扫描线中即可.如何判断一个立方体包括了区间[1,10]呢? 只要该立方体的Z轴最小值<=1且Z轴最大值>1,那么它就必然包括了区间[1,10].想想是不是.

       对于每个给定的Z轴区间,我们只要求出交>=3次以上的总面积res,然后用res*该Z轴区间长度,即可求出该区间的ans体积.由于X轴的范围也很大,所以X轴也需要离散化处理.

       线段树需要维护的信息有:

cover:值为0,1,2,3,4… 表示当前节点控制的X轴区被覆盖的次数.

sum: 表示当前节点控制的X轴区域被覆盖次数>=3的总长度

len1: 表示当前节点控制的X轴区域被覆盖次数=1的总长度

len2: 示当前节点控制的X轴区域被覆盖次数=2的总长度

具体实现见代码.

AC代码:1468ms

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN=2222;#define lson i*2,l,m#define rson i*2+1,m+1,rint cover[MAXN*4],sum[MAXN*4],len1[MAXN*4],len2[MAXN*4];int X[MAXN],Z[MAXN];int cnt_x,cnt_z;struct seg{    int l,r,h,d;    seg(){}    seg(int a,int b,int c,int d):l(a),r(b),h(c),d(d){}    bool operator < (const seg& b)const    {        return h<b.h;    }}ss[MAXN];struct point{    int x,y,z;    void read()    {        scanf("%d%d%d",&x,&y,&z);    }};struct cube{    point a,b;}cubes[MAXN];void PushUp(int i,int l,int r){    if(cover[i]>=3)    {        sum[i]=X[r+1]-X[l];        len1[i]=len2[i]=0;    }    else if(cover[i]==2)    {        sum[i]=sum[i*2]+sum[i*2+1]+len1[i*2]+len1[i*2+1]+len2[i*2]+len2[i*2+1];        len2[i]=X[r+1]-X[l]-sum[i];        len1[i]=0;    }    else if(cover[i]==1)    {        sum[i]=sum[i*2]+sum[i*2+1]+len2[i*2]+len2[i*2+1];        len2[i]=len1[i*2]+len1[i*2+1];        len1[i]=X[r+1]-X[l]-sum[i]-len2[i];    }    else    {        sum[i]=sum[i*2]+sum[i*2+1];        len1[i]=len1[i*2]+len1[i*2+1];        len2[i]=len2[i*2]+len2[i*2+1];    }}void update(int ql,int qr,int v,int i,int l,int r){    if(ql<=l&&r<=qr)    {        cover[i]+=v;        PushUp(i,l,r);        return ;    }    int m=(l+r)>>1;    if(ql<=m) update(ql,qr,v,lson);    if(m<qr) update(ql,qr,v,rson);    PushUp(i,l,r);}int main(){    int T;    scanf("%d",&T);    for(int kase=1;kase<=T;kase++)    {        int n;        cnt_x=cnt_z=0;        scanf("%d",&n);        for(int i=1;i<=n;i++)        {            cubes[i].a.read();            cubes[i].b.read();            X[cnt_x++]=cubes[i].a.x;            X[cnt_x++]=cubes[i].b.x;            Z[cnt_z++]=cubes[i].a.z;            Z[cnt_z++]=cubes[i].b.z;        }        if(n<3)        {            printf("Case %d: 0\n",kase);            continue;        }        sort(X,X+cnt_x);        sort(Z,Z+cnt_z);        cnt_x=unique(X,X+cnt_x)-X;        cnt_z=unique(Z,Z+cnt_z)-Z;        long long ans=0;        for(int i=0;i<cnt_z-1;i++)        {            int cnt=0;            long long res=0;            for(int j=1;j<=n;j++)            {                if(cubes[j].a.z<=Z[i] && cubes[j].b.z>Z[i])                {                    ss[cnt++]=seg(cubes[j].a.x,cubes[j].b.x,cubes[j].a.y,1);                    ss[cnt++]=seg(cubes[j].a.x,cubes[j].b.x,cubes[j].b.y,-1);                }            }            sort(ss,ss+cnt);            memset(cover,0,sizeof(cover));            memset(sum,0,sizeof(sum));            memset(len1,0,sizeof(len1));            memset(len2,0,sizeof(len2));            for(int j=0;j<cnt-1;j++)            {                int ql=lower_bound(X,X+cnt_x,ss[j].l)-X;                int qr=lower_bound(X,X+cnt_x,ss[j].r)-X-1;                update(ql,qr,ss[j].d,1,0,cnt_x-1);                res +=(long long)sum[1]*(ss[j+1].h-ss[j].h);            }            ans += res*(Z[i+1]-Z[i]);        }        printf("Case %d: %I64d\n",kase,ans);    }}


0 0
原创粉丝点击