亚特兰蒂斯
题意:给n个矩形到一个平面上,求他们的总面积。
思路:将他们的x坐标从小到大排序,然后根据对于当前x坐标而言他们的y坐标区间进行相应的维护某些变化,这种解题思路就是扫描线。对于这题,我们要维护的是y区间的覆盖情况。
然后用覆盖的总长度去乘以当前两个x之间的距离,再全部加起来就是答案。对于如何去计算每一个x后的y区间覆盖情况,我们可以令(x1,y1,y2,1)表示左区间,(x2,y1,y2,-1)为右区间。因为
去累加的时候相当于在x2后面的就没覆盖到了。也就是说只有x1~x2的[y1,y2]区间被覆盖,还要维护个cnt表示被覆盖的次数。因为数据太大且为double记得离散化。
#include<cstring> #include<algorithm> #include<vector> #include<map> #include<queue> #include<cstdio> #include<cmath> #define ll long long #define lowbit(x) x&(-x) using namespace std; const int N=1000+10; struct node{ double x,y1,y2; int val; node() {} node(double x, double y1, double y2,int val){ this->x = x; this->val = val; this->y1 = y1; this->y2 = y2; } bool operator <(const node &t)const { return x<t.x; } }; struct Tree { int l; int r; double len; int cnt; } t[N*2]; vector<node> a; vector<double> y; int n; void pushup(int p) { int l=t[p].l; int r=t[p].r; if(t[p].cnt>0) { t[p].len=y[r+1]-y[l]; } else { t[p].len=t[p<<1].len+t[p<<1|1].len; } } void build(int p,int l,int r) { t[p].l=l; t[p].r=r; t[p].cnt=t[p].len=0; if(l==r) return; int mid=(l+r)>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r); } void update(int p,int l,int r,int val) { if(t[p].l>=l&&t[p].r<=r) { t[p].cnt+=val; pushup(p); return; } int mid=(t[p].l+t[p].r)>>1; if(l<=mid) update(p<<1,l,r,val); if(r>mid) update(p<<1|1,l,r,val); pushup(p); } int main() { int k=1; while(~scanf("%d",&n)) { if(n==0) break; y.clear(); a.clear(); for(int i=0;i<n;i++) { double x1,x2,y1,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); y.push_back(y1); y.push_back(y2); a.push_back(node(x1,y2,y1,1)); a.push_back(node(x2,y2,y1,-1)); } y.push_back(-1); sort(a.begin(),a.end()); sort(y.begin(),y.end()); y.erase(unique(y.begin(),y.end()),y.end()); int m=y.size(),num=a.size(); build(1,0,m); double ans = 0.0; for(int i=0;i<num;i++) { int l=lower_bound(y.begin(),y.end(),a[i].y2)-y.begin(); int r=lower_bound(y.begin(),y.end(),a[i].y1) - y.begin()-1; update(1,l,r,a[i].val); ans+=t[1].len*(a[i+1].x-a[i].x); } printf("Test case #%d\n",k++); printf("Total explored area: %.2lf\n\n",ans); } return 0; }