【线段树+扫描线】HDU 1542+1255

来源:互联网 发布:金庸群侠传 lua 源码 编辑:程序博客网 时间:2024/05/16 23:38
【线段树+扫描线】
简单的说就是从下到上扫描线段,累加记录该线段添加进去之后在总区间的映射有效长度*高度差。


线段树扫描线详解:矩形面积的并:http://www.cnblogs.com/scau20110726/archive/2013/04/12/3016765.html

矩形面积的交:http://www.cnblogs.com/scau20110726/archive/2013/04/14/3020998.html

看了这两篇博客+代码才有所理解。因为扫描的是线段,在线段树中分界点那部分区间可能无法表示,然后就变成了区间左闭右开[l,r),在更新的时候我们可以只更新闭区间即[l,r-1],在记录结果的时候把那个在加上。自己动手画图模拟会有更深的理解。


注意数据的离散化。。。

col[root]枚举到当前边的时候,下方有多少有用线段。(该区间矩形的下边比上边多几条)

即当前结点区间的覆盖情况,不必向下更新,当遇到矩形的上边的时候,直接更新当前结点。
sum[root]区间被覆盖的长度

summ[root]区间被重复覆盖的长度/*注意更新*/


HDU 1542 【矩形面积的并】CODE:

#include<stdio.h>#include<string.h>#include<algorithm>#include<queue>#include<stack>#include<math.h>#include<map>#include<iostream>#define INF 0x3f3f3f3f#define lson l,m,root<<1#define rson m+1,r,root<<1|1typedef  long long LL;using namespace std;const int mod=998244353;const int maxn=5005;double sum[maxn<<2],X[maxn<<2];int col[maxn<<2];struct node{    double l,r,h;    int s;    node() {};    node(double a,double b,double c,int d)    {        l=a,r=b,h=c;        s=d;    }    bool operator <(const node &cmp)const    {        return h<cmp.h;    }}ss[maxn<<2];void pushup(int l,int r,int root){    if(col[root])        sum[root]=X[r+1]-X[l];//*********    else if(l==r)        sum[root]=0;    else        sum[root]=sum[root<<1]+sum[root<<1|1];}void update(int L,int R,int c,int l,int r,int root){    if(L<=l&&r<=R)    {        col[root]+=c;        pushup(l,r,root);        return;    }    int m=(l+r)>>1;    if(L<=m)        update(L,R,c,lson);    if(R>m)        update(L,R,c,rson);    pushup(l,r,root);}int main(){   int n,T=0;   while(~scanf("%d",&n)&&n)   {       int m=0,k=1;       double a,b,c,d;       for(int i=0;i<n;i++)       {           scanf("%lf%lf%lf%lf",&a,&b,&c,&d);           X[m]=a;           ss[m++]=node(a,c,b,1);           X[m]=c;           ss[m++]=node(a,c,d,-1);       }       sort(X,X+m);       sort(ss,ss+m);       for(int i=1;i<m;i++)       {           if(X[i]!=X[i-1])            X[k++]=X[i];       }       double ans=0;       memset(col,0,sizeof(col));       memset(sum,0,sizeof(sum));       for(int i=0;i<m-1;i++)       {           int l=lower_bound(X,X+k,ss[i].l)-X;           int r=lower_bound(X,X+k,ss[i].r)-X-1;//******           if(l<=r)            update(l,r,ss[i].s,0,k-1,1);           ans+=sum[1]*(ss[i+1].h-ss[i].h);       }       printf("Test case #%d\nTotal explored area: %.2lf\n\n",++T,ans);//注意格式   }}


HDU 1225【矩形面积的交】 CODE:

summ[]数组的更新:1、col[root]>1,即该区间全部被覆盖了两次及两次以上,长度就是该区间的长度;

                                 2、l==r最底层的叶子节点,无论覆盖没覆盖,都为0;

                                 3、col[root]=1,左右子节点覆盖一次及一次以上的和(因为col[]没有向下更新,如果子区间有被                                 覆盖的,则就是被重复覆盖的);

                                 4、其他,左右子节点覆盖两次及两次以上的和。

#include<stdio.h>#include<string.h>#include<algorithm>#include<queue>#include<stack>#include<math.h>#include<map>#include<iostream>#define INF 0x3f3f3f3f#define lson l,m,root<<1#define rson m+1,r,root<<1|1typedef  long long LL;using namespace std;const int mod=998244353;const int maxn=5005;double sum[maxn<<2],X[maxn<<2];double summ[maxn<<2];int col[maxn<<2];struct node{    double l,r,h;    int s;    node() {};    node(double a,double b,double c,int d)    {        l=a,r=b,h=c;        s=d;    }    bool operator <(const node &cmp)const    {        return h<cmp.h;    }} ss[maxn<<2];void pushup(int l,int r,int root){    if(col[root])        sum[root]=X[r+1]-X[l];    else if(l==r)        sum[root]=0;    else        sum[root]=sum[root<<1]+sum[root<<1|1];    if(col[root]>1)        summ[root]=X[r+1]-X[l];    else if(l==r)        summ[root]=0;    else if(col[root]==1)        summ[root]=sum[root<<1]+sum[root<<1|1];    else        summ[root]=summ[root<<1]+summ[root<<1|1];}void update(int L,int R,int c,int l,int r,int root){    if(L<=l&&r<=R)    {        col[root]+=c;        pushup(l,r,root);        return;    }    int m=(l+r)>>1;    if(L<=m)        update(L,R,c,lson);    if(R>m)        update(L,R,c,rson);    pushup(l,r,root);}int main(){    int n,t;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        int m=0,k=1;        double a,b,c,d;        for(int i=0; i<n; i++)        {            scanf("%lf%lf%lf%lf",&a,&b,&c,&d);            X[m]=a;            ss[m++]=node(a,c,b,1);            X[m]=c;            ss[m++]=node(a,c,d,-1);        }        sort(X,X+m);        sort(ss,ss+m);        for(int i=1; i<m; i++)        {            if(X[i]!=X[i-1])                X[k++]=X[i];        }        double ans=0;        memset(col,0,sizeof(col));        memset(sum,0,sizeof(sum));        memset(summ,0,sizeof(summ));        for(int i=0; i<m-1; i++)        {            int l=lower_bound(X,X+k,ss[i].l)-X;            int r=lower_bound(X,X+k,ss[i].r)-X-1;            if(l<=r)                update(l,r,ss[i].s,0,k-1,1);           // cout<<l<<" "<<r<<"---"<<sum[1]<<endl;            ans+=summ[1]*(ss[i+1].h-ss[i].h);        }        printf("%.2lf\n",ans);    }}


原创粉丝点击