首页 > 代码库 > codevs 3044 矩形面积求并 (扫描线)

codevs 3044 矩形面积求并 (扫描线)

/*之前一直偷懒离散化+暴力做着题 今天搞一下扫描线 自己按照线段树的一般写法写的有些问题因为不用于以前的区间sumso题解搬运者23333Orz~ 去掉了打标记的过程同时更新区间的时候先判断是不是已经需要赋值还有一些细节的处理线段树是离散化之后的x轴建的每个线段的权值转移到点上每个点代表他右侧一小段的长度所以修改[l,r]变为[l,r-1] 另外维护lazy 表示这个区间压了几次只要lazy[k]>0 s[k]就存着值碰到顶边就lazy--每次计算面积用的是s[1] 也就是整个线段的覆盖部分对于每次的修改时候查询的时候只是上传 最后拿s[1]计算所以不用下放lazy了就 */#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define maxn 1010#define lc k*2#define rc k*2+1#define mid (l+r)/2using namespace std;int n,m,lazy[maxn*4];double B[maxn],s[maxn*4],ans;struct node{    double x1,x2,y;    int falg;}A[maxn];int cmp(const node &x,const node &y){    return x.y<y.y;}void up(int k,int l,int r){    if(lazy[k])s[k]=B[r+1]-B[l];    else if(l==r)s[k]=0;    else s[k]=s[lc]+s[rc];}void Change(int k,int l,int r,int x,int y,int z){    if(x<=l&&y>=r){        lazy[k]+=z;up(k,l,r);return;    }    if(x<=mid)Change(lc,l,mid,x,y,z);    if(y>mid)Change(rc,mid+1,r,x,y,z);    up(k,l,r);}int main(){    while(1){        scanf("%d",&n);        if(n==0)break;m=0;        memset(s,0,sizeof(s));        memset(lazy,0,sizeof(lazy));        double a,b,c,d;        int l,r;ans=0;        for(int i=1;i<=n;i++){            scanf("%lf%lf%lf%lf",&a,&b,&c,&d);            A[++m].x1=a;A[m].x2=c;A[m].y=b;A[m].falg=1;B[m]=a;            A[++m].x1=a;A[m].x2=c;A[m].y=d;A[m].falg=-1;B[m]=c;        }        sort(B+1,B+1+m);sort(A+1,A+1+m,cmp);        for(int i=1;i<=m;i++){            l=lower_bound(B+1,B+1+m,A[i].x1)-B;            r=lower_bound(B+1,B+1+m,A[i].x2)-B-1;            if(l<=r)Change(1,1,m,l,r,A[i].falg);            ans+=(double)(s[1]*(A[i+1].y-A[i].y));        }        printf("%.2f\n",ans);    }    return 0;}

 

codevs 3044 矩形面积求并 (扫描线)