HDU 1828 Picture(线段树求矩形周长并)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1828

题意:矩形周长并。

思路:节点保存的是一段,这一段的长度以及横向线段的个数。





struct node

{

    int L,R,len,sum,segCount,coverNum;

    int LcoverNum,RcoverNum;

};



struct line

{

    int x,y1,y2,flag;



    line(){}

    line(int _x,int _y1,int _y2,int _flag)

    {

        x=_x;

        y1=_y1;

        y2=_y2;

        flag=_flag;

    }

};



node a[N*3];

line L[N];

int y[N],n,yNum,LNum;





struct pol

{

    int x1,y1,x2,y2;



    void get()

    {

        RD(x1,y1);

        RD(x2,y2);

        if(x1>x2) swap(x1,x2);

        if(y1>y2) swap(y1,y2);

    }

};



pol p[N];



int cmp(line a,line b)

{

    return a.x<b.x;

}



int find(int x)

{

    int low=0,high=yNum-1,mid;

    while(low<=high)

    {

        mid=(low+high)>>1;

        if(y[mid]==x) return mid;

        if(y[mid]>x) high=mid-1;

        else low=mid+1;

    }

}



void build(int t,int L,int R)

{

    a[t].L=L;

    a[t].R=R;

    a[t].coverNum=0;

    a[t].segCount=0;

    a[t].sum=0;

    a[t].LcoverNum=a[t].RcoverNum=0;

    a[t].len=y[R]-y[L];

    if(L+1<R)

    {

        int mid=(L+R)>>1;

        build(t*2,L,mid);

        build(t*2+1,mid,R);

    }

}



void up(int t)

{

    if(a[t].coverNum>0) a[t].sum=a[t].len;

    else if(a[t].L+1<a[t].R) a[t].sum=a[t*2].sum+a[t*2+1].sum;

    else a[t].sum=0;



    if(a[t].coverNum>0)

    {

        a[t].LcoverNum=a[t].RcoverNum=1;

        a[t].segCount=1;

    }

    else if(a[t].L+1<a[t].R)

    {

        a[t].LcoverNum=a[t*2].LcoverNum;

        a[t].RcoverNum=a[t*2+1].RcoverNum;

        a[t].segCount=a[t*2].segCount+a[t*2+1].segCount-a[t*2].RcoverNum*a[t*2+1].LcoverNum;

    }

    else

    {

        a[t].LcoverNum=a[t].RcoverNum=0;

        a[t].segCount=0;

    }

}



void insert(int t,int L,int R,int det)

{

    int mid=(a[t].L+a[t].R)>>1;

    if(a[t].L==L&&a[t].R==R) a[t].coverNum+=det;

    else if(R<=mid) insert(t*2,L,R,det);

    else if(L>=mid) insert(t*2+1,L,R,det);

    else

    {

        insert(t*2,L,mid,det);

        insert(t*2+1,mid,R,det);

    }

    up(t);

}





int cal(pol p[],int n)

{

    LNum=yNum=0;

    int i,x1,y1,x2,y2;

    FOR0(i,n)

    {

        x1=p[i].x1; y1=p[i].y1;

        x2=p[i].x2; y2=p[i].y2;

        L[LNum++]=line(x1,y1,y2,1);

        L[LNum++]=line(x2,y1,y2,-1);

        y[yNum++]=y1;

        y[yNum++]=y2;

    }

    sort(y,y+yNum);

    sort(L,L+LNum,cmp);

    yNum=unique(y,y+yNum)-y;



    build(1,0,yNum-1);

    int ans=0,preLen=0;

    for(i=0;i+1<LNum;i++)

    {

        x1=find(L[i].y1);

        x2=find(L[i].y2);

        insert(1,x1,x2,L[i].flag);

        ans+=2*a[1].segCount*(L[i+1].x-L[i].x);

        ans+=abs(a[1].sum-preLen);

        preLen=a[1].sum;

    }

    insert(1,find(L[i].y1),find(L[i].y2),-1);

    ans+=abs(a[1].sum-preLen);

    return ans;

}



int main()

{

    while(scanf("%d",&n)!=-1)

    {

        int i;

        FOR0(i,n) p[i].get();

        PR(cal(p,n));

    }

    return 0;

}

 
   

  

 
  

你可能感兴趣的:(HDU)