zoukankan      html  css  js  c++  java
  • Get The Treasury HDU

    题意: 给若干个长方体,求出长方体至少相交三次的总体积;
    分析:经典扫描线的题,z的范围不高于500,且只有1000个点,可以考虑在外层循环枚举z -500~500,也可以直接类似于扫描线一样,把z存在数组里, 每次算出来相交面积,ans+=z[i+1]-z[i];

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=2e3+5;
    const int inf=0x3f3f3f3f;
    #define ls (i<<1)
    #define rs (i<<1|1)
    struct line
    {
        int x1,x2,z1,z2,y,flag;
        line(){}
        line(int t1,int t2,int t3,int t4,int t5,int t6)
        {
            x1=t1; x2=t2; z1=t3; z2=t4; y=t5; flag=t6;
        }
    };
    struct node
    {
        int s1,s2,s3,cov;///s1表示覆盖大于等于1的和,s2,s3同理
        void clr(){ s1=s2=s3=cov=0; }
    };
    line a[N<<1],b[N<<1];
    node tree[N<<2];
    int temp[N<<1],zz[N<<1],n,m;
    bool cmp(line p,line q)
    {
        return p.y<q.y;
    }
    void pushup(int i,int l,int r)
    {
        int c=tree[i].cov;
        if(c)
        {
            tree[i].s1=temp[r+1]-temp[l];//若覆盖了,s1=区间长度,temp是离散化的数组
            if(c>=2)
            {
                tree[i].s2=temp[r+1]-temp[l];
                if(c>=3) tree[i].s3=temp[r+1]-temp[l];
                else if(l==r) tree[i].s3=0;
                else tree[i].s3=tree[ls].s1+tree[rs].s1;//若c==2 ,则父亲已经被覆盖了2次,那么只需找儿子覆盖了1次的就行
            }
            else if(l==r) tree[i].s2=tree[i].s3=0;
            else
            {
                tree[i].s3=tree[ls].s2+tree[rs].s2;//同上
                tree[i].s2=tree[ls].s1+tree[rs].s1;
            }
        }
        else if(l==r) tree[i].s1=tree[i].s2=tree[i].s3=0;
        else
        {
            tree[i].s3=tree[ls].s3+tree[rs].s3;
            tree[i].s2=tree[ls].s2+tree[rs].s2;
            tree[i].s1=tree[ls].s1+tree[rs].s1;
        }
    }
    void build(int i,int l,int r)
    {
        tree[i].clr();
        if(l==r) return;
        int mid=(l+r)>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
    }
    void update(int i,int l,int r,int ll,int rr,int v)
    {
        if(ll<=l&&r<=rr)
        {
            tree[i].cov+=v;
            pushup(i,l,r);
            return;
        }
        int mid=(l+r)>>1;
        if(mid>=ll) update(ls,l,mid,ll,rr,v);
        if(mid<rr) update(rs,mid+1,r,ll,rr,v);
        pushup(i,l,r);
    }
    int main()
    {
        int T,test=0;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
            {
                int x1,x2,z1,y1,y2,z2;
                scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
                a[i]=line(x1,x2,z1,z2,y1,1);
                a[i+n]=line(x1,x2,z1,z2,y2,-1);
                temp[i]=x1; temp[i+n]=x2;
                zz[i]=z1; zz[i+n]=z2;
            }
            //排序去重离散化
            n<<=1;
            sort(a+1,a+n+1,cmp);
            sort(temp+1,temp+1+n);
            sort(zz+1,zz+n+1);
            int k=unique(zz+1,zz+n+1)-zz-1;
            m=unique(temp+1,temp+n+1)-temp-1;
            for(int i=1;i<=n;i++)
            {
                a[i].x1=lower_bound(temp+1,temp+m+1,a[i].x1)-temp;
                a[i].x2=lower_bound(temp+1,temp+m+1,a[i].x2)-temp;
            }
            LL ans=0;
            for(int i=1;i<k;i++)
            {
    
                int tot=0;
                build(1,1,m-1);
                for(int j=1;j<=n;j++)//选取与z=zz[i]平面相交的立方体,但为了避免重复取,改为左开右闭
                {
                    if(a[j].z1<=zz[i]&&zz[i]<a[j].z2)
                        b[++tot]=a[j];
                }
                LL d=zz[i+1]-zz[i];
                for(int j=1;j<tot;j++)
                {
                    if(b[j].x1<b[j].x2)
                    {
                        update(1,1,m-1,b[j].x1,b[j].x2-1,b[j].flag);
                        ans+=d*tree[1].s3*(b[j+1].y-b[j].y);
                    }
                }
            }
            printf("Case %d: %lld
    ",++test,ans);
        }
        return 0;
    }

    总结:一道扫描线变形的好题,思维难度不高,但编程细节较多,做这道题的时候WA了很多次,思路没有问题,后面重新写了一道又过了。。。(因果循环,报应不爽)

    展望:做一个善良的人,别被坏事缠身。重塑正气,再战心魔!!!

  • 相关阅读:
    SpringCloud之Nacos服务注册(十八)
    SpringCloud之Nacos服务发现(十七)
    Pillow模块图片生成
    js中==和===区别
    jQuery跳转到另一个页面以及原生js跳转到另一个页面
    django搭建BBS-登入&验证码的生成
    django搭建BBS-表单创建&注册
    POJ3784 Running Median
    POJ 2559 Largest Rectangle in a Histogram
    Codevs1299 切水果
  • 原文地址:https://www.cnblogs.com/DeepJay/p/12025216.html
Copyright © 2011-2022 走看看