HDU 1255 线段树扫描线面积交

来源:互联网 发布:成都卧龙大数据 苏明亮 编辑:程序博客网 时间:2024/04/27 23:20

题意:很多矩形会有重叠至少两次的地方,现在问重叠至少两次的面积。


想法:线段树扫描线,对于一个区间[x,y],用cover表示这个区间整体被覆盖的次数,用one表示这个区间只被覆盖一次的长度,more表示这个区间被覆盖至少两次的长度。用seglen表示这个区间的长度,那么one+more=seglen,下面我们来讨论他们的关系。

1.cover>=2:表示这个区间已经被至少覆盖了两次,显然是我们要求的,所以直接把长度推上去。

2.cover=1:表示这个区间已经被覆盖正好一次,显然我们可以想到在这个区间内,可能存在有一部分存在覆盖两次的情况,因为cover表示的是整个区间的覆盖情况,并不能表示细节。所以这个区间要询问他的左右孩子,只要他们至少被覆盖一次,那么就可以算上,因为这个区间本身就已经有了一次覆盖了。

3.cover=0:表示这个区间没有被覆盖,显然有可能有一部分是有覆盖情况的,所以需要询问他的左右孩子。

以上就是面积交的pushup函数的主要思想了。


#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define LL(x) x<<1#define RR(x) x<<1|1using namespace std;const int nodes=1005;int n;struct node{    double l,r,h;    int f;}bian[nodes*2];struct nodee{    int lft,rht;    int cover;    double more,one;    int mid()    {        return (lft+rht)/2;    }};double pos[nodes*2];bool cmp(node a,node b){    return a.h<b.h;}int bin_search(double num,int l,int r){    while(l<=r)    {        int mid=(l+r)/2;        if(pos[mid]==num) return mid;        else if(pos[mid]<num)        {            l=mid+1;        }        else r=mid-1;    }    return -1;}class Seg{    public:        nodee tree[nodes*8];        void get_len(int index)        {            if(tree[index].cover>=2)             {                tree[index].more=tree[index].one=pos[tree[index].rht+1]-pos[tree[index].lft];            }            else if(tree[index].cover==1)            {                tree[index].one=pos[tree[index].rht+1]-pos[tree[index].lft];                if(tree[index].lft==tree[index].rht) tree[index].more=0;                else tree[index].more=tree[LL(index)].one+tree[RR(index)].one;            }            else             {                if(tree[index].lft==tree[index].rht) tree[index].more=tree[index].one=0;                else                 {                    tree[index].more=tree[LL(index)].more+tree[RR(index)].more;                    tree[index].one=tree[LL(index)].one+tree[RR(index)].one;                }            }        }        void build(int lft,int rht,int index)        {            tree[index].lft=lft;            tree[index].rht=rht;            tree[index].more=0;            tree[index].one=0;            tree[index].cover=0;            if(lft!=rht)            {                int mid=tree[index].mid();                build(lft,mid,LL(index));                build(mid+1,rht,RR(index));            }        }        void updata(int s,int t,int val,int index)        {            int lft=tree[index].lft;            int rht=tree[index].rht;            if(s<=lft&&rht<=t)            {                tree[index].cover+=val;                get_len(index);                return;            }            int mid=tree[index].mid();            if(s<=mid) updata(s,t,val,LL(index));            if(t>mid) updata(s,t,val,RR(index));            get_len(index);        }}seg;int main(){    int ca=1;    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        int cnt=0,cnt1=1;        for(int i=1;i<=n;i++)        {            double a,b,c,d;            scanf("%lf%lf%lf%lf",&a,&b,&c,&d);            pos[cnt]=a;bian[cnt].l=a;bian[cnt].r=c;bian[cnt].h=b;bian[cnt].f=1;                        pos[cnt+1]=c;bian[cnt+1].l=a;bian[cnt+1].r=c;bian[cnt+1].h=d;bian[cnt+1].f=-1;            cnt+=2;        }        sort(pos,pos+cnt);        sort(bian,bian+cnt,cmp);        for(int i=1;i<cnt;i++)        {            if(pos[i]!=pos[i-1])            {                pos[cnt1++]=pos[i];            }        }        double sum=0;        seg.build(0,cnt1-1,1);        for(int i=0;i<cnt-1;i++)        {            int l=bin_search(bian[i].l,0,cnt1-1);            int r=bin_search(bian[i].r,0,cnt1-1)-1;            seg.updata(l,r,bian[i].f,1);            double hh=seg.tree[1].more;            sum+=(bian[i+1].h-bian[i].h)*hh;        }        printf("%.2lf\n",sum);    }    return 0;} 

0 0
原创粉丝点击