题目描述 Description |
输入n个矩形,求他们总共占地面积(也就是求一下面积的并) |
输入描述 Input Description |
可能有多组数据,读到n=0为止(不超过15组) 每组数据第一行一个数n,表示矩形个数(n<=100) 接下来n行每行4个实数x1,y1,x2,y1(0 <= x1 < x2 <= 100000;0 <= y1 < y2 <= 100000),表示矩形的左下角坐标和右上角坐标 |
输出描述 Output Description |
每组数据输出一行表示答案 |
样例输入 Sample Input |
2 |
样例输出 Sample Output |
180.00 |
数据范围及提示 Data Size & Hint |
无 |
矩形面积并,扫描线+线段树
本题的线段树比较奇怪
其中的坑点在pushup,线段树维护的区间[l,r]如果l,r相等并不是一段空集,而是线段pos[l]-pos[r+1] 这一线段
#include<iostream> #include<algorithm> #include<cstdio> #include<queue> #include<cmath> #include<cstring> using namespace std; typedef long long LL; typedef pair<int,int> PII; #define mem(a,b) memset(a,b,sizeof(a)) inline int read() { int x=0,f=1;char c=getchar(); while(!isdigit(c)){if(c==‘-‘)f=-1;c=getchar();} while(isdigit(c)){x=x*10+c-‘0‘;c=getchar();} return x*f; } const int maxn=210; int n,add[maxn<<2]; double a,b,c,d,pos[maxn],sum[maxn<<2],ans; struct segment { double X,x,Y;int tag; segment(){} segment(double _1,double _2,double _3,int _4):X(_1),x(_2),Y(_3),tag(_4) {} bool operator < (const segment &s)const {return Y<s.Y;} }seg[maxn]; void pushup(int l,int r,int o) { if(add[o])sum[o]=pos[r+1]-pos[l]; else if(l==r)sum[o]=0; else sum[o]=sum[o<<1]+sum[o<<1|1]; } void update(int l,int r,int o,int L,int R,int c) { if(L==l && r==R) { add[o]+=c; pushup(l,r,o); return; } int mid=(l+r)>>1,lo=o<<1,ro=lo|1; if(R<=mid)update(l,mid,lo,L,R,c); else if(L>mid)update(mid+1,r,ro,L,R,c); else update(l,mid,lo,L,mid,c),update(mid+1,r,ro,mid+1,R,c); pushup(l,r,o); } int main() { while(scanf("%d",&n)!=EOF && n) { mem(pos,0);mem(sum,0);mem(add,0);ans=0; for(int i=1;i<=n;i++) { scanf("%lf%lf%lf%lf",&a,&b,&c,&d); seg[i*2]=segment(a,c,b,1);pos[i*2]=a; seg[i*2-1]=segment(a,c,d,-1);pos[i*2-1]=c; } sort(seg+1,seg+n*2+1);sort(pos+1,pos+n*2+1); for(int i=1;i<=2*n;i++) { int l=lower_bound(pos+1,pos+n*2+1,seg[i].X)-pos; int r=lower_bound(pos+1,pos+n*2+1,seg[i].x)-pos-1; update(1,2*n,1,l,r,seg[i].tag); ans+=sum[1]*(seg[i+1].Y-seg[i].Y); } printf("%.2lf\n",ans); } return 0; }
时间: 2024-10-10 01:22:28