zoukankan      html  css  js  c++  java
  • hdu3265一种错误的做法

    题目链接

    这是求面积并的题目,刚开始我的思路是将挖去的矩形的入边和出边覆盖效果颠倒,

    即入边-1,出边+1,后来调试到爆炸,发现这是错误的做法。。原因就是对最简单

    的面积并问题没有搞清楚。刚开始接触扫描线的时候我就有一个问题,为什么覆盖

    次数不需要向子区间传递,但是我没有仔细去想这个问题,直到遇到这道题目。在

    求相交矩形面积并的过程中,所有的线段都是成对出现,重点在于所有线段的覆盖

    都是整段整段的操作,所以不需要向下传。而这道题目用这种做法就会出现一个区

    间被较小的区间释放的情况,所以会出错。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=310;//最多矩形个数
    struct edge{
        int x1,x2,y;
        int f;//1表示入,-1表示出
        edge(){}
        edge(int _x1,int _x2,int _y,int _f){
            x1=_x1,x2=_x2,y=_y,f=_f;
        }
        bool operator <(edge &e){
            if(y!=e.y)
                return y<e.y;
            return f>e.f;
        }
    };
    int nVx;
    int Vx[maxn*4];
    int nSgs;
    edge Sgs[maxn*4];
    int num[maxn*4*4];
    int len[maxn*4*4];
    void build(int root,int l,int r)
    {
        num[root]=len[root]=0;
        if(l==r)return;
        int mid=(l+r)/2;
        build(root*2,l,mid);
        build(root*2+1,mid+1,r);
    }
    void pushUp(int root,int l,int r)
    {
        if(num[root]!=0)len[root]=Vx[r+1]-Vx[l];
        else if(l==r)len[root]=0;
        else len[root]=len[root*2]+len[root*2+1];
        printf("%d %d num[%d]=%d
    ",l,r,root,num[root]);
    }
    void update(int root,int L,int R,int f,int l,int r)
    {
        //printf("%d %d %d %d %d %d
    ",root,L,R,f,l,r);
        if(L<=l&&r<=R){
            num[root]+=f;
            pushUp(root,l,r);
            return ;
        }
        int mid=(l+r)/2;
        if(L<=mid)update(root*2,L,R,f,l,mid);
        if(mid<R)update(root*2+1,L,R,f,mid+1,r);
        pushUp(root,l,r);
    }
    int bin(int k)
    {
        int l=0,r=nVx-1,mid;
        while(l<=r){
            mid=(l+r)/2;
            if(Vx[mid]==k)return mid;
            else if(Vx[mid]>k)r=mid-1;
            else l=mid+1;
        }
        return -1;
    }
    int myUnique(int a[],int n)
    {
        int sz=1;
        for(int i=1;i<n;i++){
            if(a[i]!=a[i-1])a[sz++]=a[i];
        }
        return sz;
    }
    int main()
    {
        freopen("in.txt","r",stdin);
        int N;
        while(scanf("%d",&N)!=EOF&&N!=0){
            nVx=0;
            nSgs=0;
            for(int i=0;i<N;i++){
                int x1,y1,x2,y2,x3,y3,x4,y4;
                scanf("%d%d%d%d%d%d%d%d",
                    &x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
                printf("%d %d %d %d %d %d %d %d
    ",
                    x1,y1,x2,y2,x3,y3,x4,y4);
                Vx[nVx++]=x1,Vx[nVx++]=x2,Vx[nVx++]=x3,Vx[nVx++]=x4;
                Sgs[nSgs++]=edge(x1,x2,y1,1);
                Sgs[nSgs++]=edge(x1,x2,y2,-1);
                Sgs[nSgs++]=edge(x3,x4,y3,-1);
                Sgs[nSgs++]=edge(x3,x4,y4,1);
            }
            sort(Vx,Vx+nVx);
            nVx=myUnique(Vx,nVx);
            sort(Sgs,Sgs+nSgs);
            build(1,0,nVx-1);
            int area=0;
            for(int i=0;i<nSgs-1;i++){
                int l=bin(Sgs[i].x1);
                int r=bin(Sgs[i].x2)-1;
                update(1,l,r,Sgs[i].f,0,nVx-1);
                printf("%d %d
    ",len[1],Sgs[i+1].y-Sgs[i].y);
                area+=len[1]*(Sgs[i+1].y-Sgs[i].y);
            }
            printf("%d
    ",area);
        }
        while(1);
    }
    View Code

     先贴一下思路:海报一张可以切割成4个矩形,然后就是普通的矩形面积并了,利

    用线段树维护即可

    正确做法

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=50310;//最多矩形个数
    struct edge{
        int x1,x2,y;
        int f;//1表示入,-1表示出
        edge(){}
        edge(int _x1,int _x2,int _y,int _f){
            x1=_x1,x2=_x2,y=_y,f=_f;
        }
        bool operator <(edge &e){
            if(y!=e.y)
                return y<e.y;
            return f>e.f;
        }
    };
    int nSgs;
    edge Sgs[maxn*8];
    int num[maxn*8];
    int len[maxn*8];
    void build(int root,int l,int r)
    {
        num[root]=len[root]=0;
        if(l==r)return;
        int mid=(l+r)/2;
        build(root*2,l,mid);
        build(root*2+1,mid+1,r);
    }
    void pushUp(int root,int l,int r)
    {
        if(num[root]!=0)len[root]=r-l+1;
        else if(l==r)len[root]=0;
        else len[root]=len[root*2]+len[root*2+1];
        //printf("%d %d num[%d]=%d
    ",l,r,root,num[root]);
    }
    void update(int root,int L,int R,int f,int l,int r)
    {
        //printf("%d %d %d %d %d %d
    ",root,L,R,f,l,r);
        if(L<=l&&r<=R){
            num[root]+=f;
            pushUp(root,l,r);
            return ;
        }
        int mid=(l+r)/2;
        if(L<=mid)update(root*2,L,R,f,l,mid);
        if(mid<R)update(root*2+1,L,R,f,mid+1,r);
        pushUp(root,l,r);
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        int N;
        while(scanf("%d",&N)!=EOF&&N!=0){
            nSgs=0;
            int lb=0,rb=maxn;
            for(int i=0;i<N;i++){
                int x1,y1,x2,y2,x3,y3,x4,y4;
                scanf("%d%d%d%d%d%d%d%d",
                    &x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
                Sgs[nSgs++]=edge(x1,x2,y1,1);
                Sgs[nSgs++]=edge(x1,x2,y3,-1);
    
                Sgs[nSgs++]=edge(x1,x3,y3,1);
                Sgs[nSgs++]=edge(x1,x3,y4,-1);
    
                Sgs[nSgs++]=edge(x4,x2,y3,1);
                Sgs[nSgs++]=edge(x4,x2,y4,-1);
    
                Sgs[nSgs++]=edge(x1,x2,y4,1);
                Sgs[nSgs++]=edge(x1,x2,y2,-1);
                lb=min(x1,lb);
                rb=max(x2,rb);
            }
            sort(Sgs,Sgs+nSgs);
            build(1,lb,rb);
            long long  area=0;
            for(int i=0;i<nSgs-1;i++){
                int l=Sgs[i].x1;
                int r=Sgs[i].x2-1;
                if(l<=r)
                    update(1,l,r,Sgs[i].f,lb,rb-1);
                //printf("%d %d
    ",len[1],Sgs[i+1].y-Sgs[i].y);
                area+=(long long)len[1]*(Sgs[i+1].y-Sgs[i].y);
            }
            printf("%lld
    ",area);
        }
        //while(1);
    }
    View Code

    参考资料

    http://www.cnblogs.com/--ZHIYUAN/p/6404732.html

  • 相关阅读:
    Atlas+Keepalived系列一:安装Atlas:
    MySQL查看当前的连接信息
    MySQL replicate-ignore-db详解
    MongoDB 进程控制系列二:结束进程
    MongoDB 进程控制系列一:查看当前正在执行的进程
    MySQL 大致测试更新时间
    MySQL SELECT 执行的具体步骤
    MongoDB副本集配置系列七:MongoDB oplog详解
    MySQL 分区
    微软BI 之SSIS 系列
  • 原文地址:https://www.cnblogs.com/MalcolmMeng/p/8456040.html
Copyright © 2011-2022 走看看