poj 1389 線段樹面積覆蓋

http://poj.org/problem?id=1389

Area of Simple Polygons
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 2772   Accepted: 1409

Description

There are N, 1 <= N <= 1,000 rectangles in the 2-D xy-plane. The four sides of a rectangle are horizontal or vertical line segments. Rectangles are defined by their lower-left and upper-right corner points. Each corner point is a pair of two nonnegative integers in the range of 0 through 50,000 indicating its x and y coordinates. 

Assume that the contour of their union is defi ned by a set S of segments. We can use a subset of S to construct simple polygon(s). Please report the total area of the polygon(s) constructed by the subset of S. The area should be as large as possible. In a 2-D xy-plane, a polygon is defined by a finite set of segments such that every segment extreme (or endpoint) is shared by exactly two edges and no subsets of edges has the same property. The segments are edges and their extremes are the vertices of the polygon. A polygon is simple if there is no pair of nonconsecutive edges sharing a point. 

Example: Consider the following three rectangles: 

rectangle 1: < (0, 0) (4, 4) >, 

rectangle 2: < (1, 1) (5, 2) >, 

rectangle 3: < (1, 1) (2, 5) >. 

The total area of all simple polygons constructed by these rectangles is 18. 

Input

The input consists of multiple test cases. A line of 4 -1's separates each test case. An extra line of 4 -1's marks the end of the input. In each test case, the rectangles are given one by one in a line. In each line for a rectangle, 4 non-negative integers are given. The first two are the x and y coordinates of the lower-left corner. The next two are the x and y coordinates of the upper-right corner.

Output

For each test case, output the total area of all simple polygons in a line. 

Sample Input

0 0 4 4
1 1 5 2
1 1 2 5
-1 -1 -1 -1
0 0 2 2
1 1 3 3
2 2 4 4
-1 -1 -1 -1
-1 -1 -1 -1  

Sample Output

18
10 

Source

這題和poj 1151一樣,就是輸入的時候複雜點。把poj 1151代碼拿過來改的。
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int N=1000+10;
struct node
{
    int l,r;
    int lf,rf,width;
    int cover;
}mem[N*6];//線段樹 lf rf 分別爲邊界 cover 爲覆蓋情況 width 爲覆蓋的寬度
struct poin
{
    int x; //記錄x座標
    int y1,y2;  //y1,y2用來記錄平行y軸的線段的兩個端點,
    int k; //標記是左邊的邊還是右邊的邊,拆點 k爲-1代表左點 1 代表右點
}point[N*2];
int Y[N*2];
bool cmp(poin a,poin b) //排序(x按照從小到大,只需要把x排序)
{
    return a.x<b.x;
}
void build(int x,int l,int r)//建樹
{
    mem[x].l=l;
    mem[x].r=r;
    mem[x].lf=Y[l];
    mem[x].rf=Y[r];
    mem[x].cover=mem[x].width=0;
    if(l+1==r) //葉子結點
    return ;
    int mid=(l+r)>>1;
    build(x*2,l,mid);//端點模型,不是格子模型
    build(x*2+1,mid,r);
}
void find(int x)//更新此處的覆蓋寬度
{
    if(mem[x].cover>0) //完全覆蓋(右點則要完全覆蓋)
    {
        mem[x].width=mem[x].rf-mem[x].lf; //求出長度
        return ;
    }
    if(mem[x].l+1==mem[x].r) // 葉子節點,wiith 爲 0
   mem[x].width=0;
    else//非葉子節點即爲下面子區間的覆蓋綜合,注意由於插入的遞歸性保證了此等式的執行順序的正確性
   mem[x].width=mem[x*2].width+mem[x*2+1].width;
}
void add(int x,int k)//加入一個點k的影響
{
    if(mem[x].lf>=point[k].y1&&mem[x].rf<=point[k].y2)//全部覆蓋 ;//直接比較實際值,顯示出了cover和標記爲1,-1的作用
    {
        mem[x].cover+=point[k].k;
        find(x);
        return ;
    }
    int mid=(mem[x].l+mem[x].r)>>1;
    if(Y[mid]<=point[k].y1)//查看 需要怎樣往下更新
    {
        add(x*2+1,k);
    }
 else if(Y[mid]>=point[k].y2)
    {
        add(x*2,k);
    }
 else
    {
        add(x*2,k);
        add(x*2+1,k);
    }
    find(x);
}
int main()
{
    //freopen("data.txt","r",stdin);
    int x1,y1,x2,y2;
    while(1)
    {
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        if(x1==-1&&y1==-1&&x2==-1&&y2==-1)
            break;
        int I=0;
        point[I].x=x1; //把座標映射到數組裏(離散化)
        point[I].y1=y1;
        point[I].y2=y2;
        point[I].k=1;
        Y[I]=y1;
        ++I;
        point[I].x=x2;
        point[I].y1=y1;
        point[I].y2=y2;
        point[I].k=-1;
        Y[I]=y2;
        ++I;
        while(1){
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            if(x1==-1&&y1==-1&&x2==-1&&y2==-1)
                break;
            point[I].x=x1; //把座標映射到數組裏(離散化)
            point[I].y1=y1;
            point[I].y2=y2;
            point[I].k=1;
            Y[I]=y1;
            ++I;
            point[I].x=x2;
            point[I].y1=y1;
            point[I].y2=y2;
            point[I].k=-1;
            Y[I]=y2;
            ++I;
        }
        sort(Y,Y+I); //縱座標排序(小到大)
        sort(point,point+I,cmp);
        build(1,0,I-1); //建樹
        add(1,0);
        int ans=0;
        for(int i=1;i<I;++i)
        {
            //cout<<i<<endl;
            ans+=(mem[1].width*(point[i].x-point[i-1].x));//每次用兩個x座標差 ×   當前覆蓋寬度
            //cout<<ans<<endl;
            add(1,i);//cout<<"TTT"<<endl;
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章