hdu1255、1542(线段树求面积的交并)

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

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

思路:

嗯哼,要开始利用线段树求解矩形面积的并、交、以及周长了。先看一下吧

给定一个矩形的左下角坐标和右上角坐标分别为:(x1,y1)、(x2,y2),对这样的一个矩形,我们构造两条线段,一条定位在x1,它在y坐标的区间是[y1,y2],并且给定一个cover域值为1;另一条线段定位在x2,区间一样是[y1,y2],给定它一个cover值为-1。根据这样的方法对每个矩形都构造两个线段,最后将所有的线段根据所定位的x从左到右进行排序。

上图中,红色的字体表示的是该线段的cover值。刚刚开始的时候,线段树上的cover值都为0,但第一根线段(x==0)插入线段树的之后,我们将线段树上的cover加上该线段的cover,那么,此时线段树上被该线段覆盖的位置上的cover的值就为1,下次再插入第二根线段(x==1)此时发现该线段所覆盖的区间内,有一部分线段树的cover为0,另有一部分为1,仔细观察,但插入第二个线段的时候,如果线段树上cover已经为1的那些区间,和现在要插入的第二根线段之间,是不是构成了并面积?还不明白?看下图,绿色部分即为插入第二根线段后得到的并面积

够清楚了吧!也就是说,我们插入某跟线段的时候,只要看该线段所在区间上的cover是否大于等于1,如果是,那么就可以将并面积值加上(目前线段的x定位 - 上一线段的x定位)*(该区间的大小)

1255:

#include<iostream>
#include<algorithm>
using namespace std;
struct node 
{
    double x,up,down;
    int flag;
}link[2005];
struct 
{
    double x,up,down;
    int cover,child;
}tree[1000000];
double yy[2005];
int cmp(const double &a,const double &b)
{
    if(a<b)
        return 1;
    else
        return 0;
}
int cmp1(const node &a,const node &b)
{
    if(a.x<b.x)
        return 1;
    else
        return 0;
}
void build(int i,int l,int r)
{
    tree[i].up=yy[r];
    tree[i].down=yy[l];
    tree[i].x=-1;
    tree[i].cover=0;
    tree[i].child=1;
    if(l+1==r)
    {
        tree[i].child=0;
        return ;
    }
    int mid=(l+r)/2;
    build(i*2,l,mid);
    build(i*2+1,mid,r);
}
double updata(int i,double l,double r,double x,int flag)
{
    if(r<=tree[i].down||l>=tree[i].up)
        return 0;
    if(!tree[i].child)
    {
        if(tree[i].cover>1)
        {
            double ans=0;
            ans=(x-tree[i].x)*(tree[i].up-tree[i].down);
            tree[i].cover+=flag;
            tree[i].x=x;
            return ans;
        }
        else
        {
            tree[i].cover+=flag;
            tree[i].x=x;
            return 0;
        }
    }
    return updata(i*2,l,r,x,flag)+updata(i*2+1,l,r,x,flag);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        int i,j=1;
        for(i=1;i<=n;i++)
        {
            double x1,y1,x2,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            link[j].x=x1;
            link[j].up=y2;
            link[j].down=y1;
            link[j].flag=1;
            yy[j]=y1;
            j++;
            link[j].x=x2;
            link[j].up=y2;
            link[j].down=y1;
            link[j].flag=-1;
            yy[j]=y2;
            j++;
        }
        sort(yy+1,yy+j,cmp);
        sort(link+1,link+j,cmp1);
        build(1,1,j-1);
        double ans=0;
        for(i=1;i<j;i++)
        {
            ans+=updata(1,link[i].down,link[i].up,link[i].x,link[i].flag);
        }
        printf("%.2lf\n",ans);
    }
    return 0;
}

 1542:

View Code
  1 #include<iostream>
  2 #include<algorithm>
  3 using namespace std;
  4 struct node
  5 {
  6     double x,up,down;
  7     int flag;
  8 }link[10000];
  9 struct node1
 10 {
 11     double x,up,down;
 12     int cover,child;
 13 }tree[100000];
 14 double yy[10000];
 15 int cmp(const double &a,const double &b)
 16 {
 17     if(a<b)
 18         return 1;
 19     else
 20         return 0;
 21 }
 22 int cmp1(const node &a,const node &b)
 23 {
 24     if(a.x<b.x)
 25         return 1;
 26     else
 27         return 0;
 28 }
 29 void build(int l,int r,int i)
 30 {
 31     int mid=(l+r)/2;
 32     tree[i].up=yy[r];
 33     tree[i].down=yy[l];
 34     tree[i].x=-1;
 35     tree[i].cover=0;
 36     tree[i].child=1;
 37     if(l+1==r)
 38     {
 39         tree[i].child=0;
 40         return ;
 41     }
 42     build(l,mid,i*2);
 43     build(mid,r,i*2+1);
 44 }
 45 double updata(int i,double down,double up,int flag,double x)
 46 {
 47     if(up<=tree[i].down||down>=tree[i].up)
 48         return 0;
 49     if(!tree[i].child)
 50     {
 51         if(tree[i].cover>0)
 52         {
 53             double ans=0;
 54             ans+=(x-tree[i].x)*(tree[i].up-tree[i].down);
 55             tree[i].x=x;
 56             tree[i].cover+=flag;
 57             return ans;
 58         }
 59         else
 60         {
 61             tree[i].x=x;
 62             tree[i].cover+=flag;
 63             return 0;
 64         }
 65     }
 66     return updata(i*2,down,up,flag,x)+updata(i*2+1,down,up,flag,x);
 67 }
 68 int main()
 69 {
 70     int n,f=0,i;
 71     while(scanf("%d",&n)>0&&n)
 72     {
 73         int j=1;
 74         for(i=1;i<=n;i++)
 75         {
 76             double x1,y1,x2,y2;
 77             scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
 78             link[j].x=x1;
 79             link[j].down=y1;
 80             link[j].up=y2;
 81             link[j].flag=1;
 82             yy[j]=y1;
 83             j++;
 84             link[j].x=x2;
 85             link[j].down=y1;
 86             link[j].up=y2;
 87             link[j].flag=-1;
 88             yy[j]=y2;
 89             j++;
 90         }
 91         sort(yy+1,yy+j,cmp);
 92         sort(link+1,link+j,cmp1);
 93         j--;
 94         double ans=0;
 95         build(1,j,1);
 96         for(i=1;i<=j;i++)
 97         {
 98             ans+=updata(1,link[i].down,link[i].up,link[i].flag,link[i].x);
 99         }
100         printf("Test case #%d\n",++f);
101 
102         printf("Total explored area: %.2lf\n\n",ans);
103     }
104     return 0;
105 }

 

posted @ 2012-11-23 08:47  紫忆  阅读(440)  评论(0编辑  收藏  举报