线段树求面积 HDU 1542 HDU 1255

来源:互联网 发布:药物研发管理 软件 编辑:程序博客网 时间:2024/06/16 06:27

参考:http://m.blog.csdn.net/tomorrowtodie/article/details/52048323

HDU 1542 求并的面积。博客里讲的很好。就是从下往上扫,然后线段树维护横坐标的总长度。

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cmath>using namespace std;const int maxn = 105;double v[maxn<<3];int f[maxn<<3];//v长度,f有没有被覆盖。struct edge{    double x1,x2;    double h;    int f;}e[maxn<<1];double x[maxn<<1];bool cmp(edge e1,edge e2){    return e1.h<e2.h;}void sert(int i,int a,int b,int f1,int l,int r){    if(l==a&&r==b)    {        f[i]+=f1;        if(f[i]>=1)        v[i]=x[b+1]-x[a];        if(f[i]==0){            if(a!=b)                v[i]=v[i<<1]+v[i<<1|1];            else v[i]=0;        }        return ;    }    int mid=(l+r)>>1;    if(b<=mid) sert(i<<1,a,b,f1,l,mid);    else if(a>=mid+1) sert(i<<1|1,a,b,f1,mid+1,r);    else {        sert(i<<1,a,mid,f1,l,mid);        sert(i<<1|1,mid+1,b,f1,mid+1,r);    }    if(f[i]<1)    v[i]=v[i<<1]+v[i<<1|1];}int main(){    int n;    int case1=1;    while(scanf("%d",&n)!=EOF&&n)    {        memset(e,0,sizeof(e));        memset(v,0,sizeof(v));        memset(f,0,sizeof(f));        memset(x,0,sizeof(x));        int h=0,k=0;        for(int i=0;i<n;i++)        {            double x1,y1,x2,y2;            scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);            e[h].x1=x1,e[h].x2=x2;e[h].h=y1;e[h].f=1;h++;            e[h].x1=x1,e[h].x2=x2;e[h].h=y2;e[h].f=-1;h++;            x[k++]=x1,x[k++]=x2;        }        sort(x,x+k);        k=unique(x,x+k)-x;        sort(e,e+h,cmp);        double ans=0.0;        printf("Test case #%d\n",case1++);        printf("Total explored area: ");        for(int i=0;i<h;i++)        {            int l=lower_bound(x,x+k,e[i].x1)-x;            int r=lower_bound(x,x+k,e[i].x2)-x-1;            sert(1,l,r,e[i].f,0,k-1);            if(i!=h-1)            ans+=(e[i+1].h-e[i].h)*v[1];        }        printf("%.2f\n\n",ans);    }    return 0;}

HDU 1255 求交的面积。
想复杂了,然后很多情况。。
我开始想的是,用v存横坐标的总长度(和求并面积一样),然后用len存重合的横坐标的总长度。然后每次,如果f[i]>1的话 ,表示len[i]=v[i]。如果f[i]==1的时候,我不知道这个时候有没有重合的,,然后我想,如果在i爸爸们,有f[i]>=1,表示len[i]=v[i]。那f[i]==0的时候,len[i]=len[i<<1]+len[i<<1|1];那么删边的时候,如果这个f[i]==1呢,开始为2,我的len[i]不是要变么,那就往下更新,一直找到下一个f[i]>=1的位置。。。
其实就是三种情况。。
f[i]>=2 len[i]=v[i];
f[i]==1 len[i]=v[i<<1]+v[i<<1|1];(a!=b)
len[i]=0;(a==b)
f[i]=0 len[i]=len[i<<1]+len[i<<1|1];(a!=b)
len[i]=0;(a==b)

#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <cmath>using namespace std;const int maxn = 1005;double v[maxn<<3],len[maxn<<3];//v,覆盖面积,len,交叉面积int f[maxn<<3];struct edge{    double x1,x2;    double h;    int f;}e[maxn<<1];double x[maxn<<1];bool cmp(edge e1,edge e2){    return e1.h<e2.h;}void sert(int i,int a,int b,int f1,int l,int r){    if(a==l&&b==r)    {        f[i]+=f1;        if(f[i]>0)            v[i]=x[b+1]-x[a];        else {            if(a==b) v[i]=0;            else v[i]=v[i<<1]+v[i<<1|1];        }        if(f[i]>=2) len[i]=v[i];        else if(f[i]==1){if(a!=b) len[i]=v[i<<1]+v[i<<1|1]; else len[i]=0;}        else {            if(a!=b)                len[i]=len[i<<1]+len[i<<1|1];            else len[i]=0;        }        return ;    }    int mid=(l+r)>>1;    if(b<=mid) sert(i<<1,a,b,f1,l,mid);    else if(a>=mid+1) sert(i<<1|1,a,b,f1,mid+1,r);    else {        sert(i<<1,a,mid,f1,l,mid);        sert(i<<1|1,mid+1,b,f1,mid+1,r);    }    if(f[i]<1)    v[i]=v[i<<1]+v[i<<1|1];    else v[i]=x[r+1]-x[l];    if(f[i]>=2) len[i]=v[i];    else if(f[i]==1) len[i]=v[i<<1]+v[i<<1|1];    else len[i]=len[i<<1]+len[i<<1|1];}int main(){    int T;    scanf("%d",&T);    while(T--)    {        memset(v,0,sizeof(v));        memset(f,0,sizeof(f));        memset(e,0,sizeof(e));        memset(x,0,sizeof(x));        memset(len,0,sizeof(len));        int n;        scanf("%d",&n);        int h=0,k=0;        for(int i=0;i<n;i++)        {            double x1,y1,x2,y2;            scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);            e[h].x1=x1,e[h].x2=x2,e[h].h=y1,e[h].f=1;h++;            e[h].x1=x1,e[h].x2=x2,e[h].h=y2,e[h].f=-1;h++;            x[k++]=x1,x[k++]=x2;        }        sort(x,x+k);        k=unique(x,x+k)-x;        sort(e,e+h,cmp);        double ans=0;        for(int i=0;i<h;i++)        {            int l=lower_bound(x,x+k,e[i].x1)-x;            int r=lower_bound(x,x+k,e[i].x2)-x-1;            sert(1,l,r,e[i].f,0,k-1);            if(i!=h-1)            ans+=len[1]*(e[i+1].h-e[i].h);        }        printf("%.2f\n",ans);    }    return 0;}
原创粉丝点击