HDU1255 覆盖的面积 扫描线

好久没写扫描线了,今天想拿些数据结构题目练手,在题目分类里面看到了这题,就拍上了。

扫描线排序离散化,线段树的区间代表y的脚标,然后对y进行离散化,二分查找对应的y。

val用来记录区间被覆盖的次数,严格O(nlogn)的访问,然后直接扫描一遍就可以了。

对精度要求不高,原来数组开小了,eps设成1e-8就WA了,不知道是数据开到1000不够还是eps太小。

 

我的代码:

 

#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> using namespace std; const double eps=1e-6; const int MAX=10100; int n,len; double sum; struct Node { int l,r,val; double area; }; Node seg[4*MAX]; struct Line { //each sub contains two lines, left and right. double x,y1,y2; bool s;//true- left, false - right bool operator<(const Line& line) const { return x<line.x; } }; Line line[2*MAX]; double line_y[2*MAX]; int Read(double num) { int left,mid,right; left=0; right=len-1; while(left<=right) { mid=(left+right)/2; if(fabs(num-line_y[mid])<eps) return mid; if(num-line_y[mid]>eps) left=mid+1; else right=mid-1; } return -1; } void Init(int k,int l,int r) //clear { seg[k].l=l; seg[k].r=r; seg[k].val=0; seg[k].area=0; if(l+1<r) { int mid=(l+r)/2; Init(2*k,l,mid); Init(2*k+1,mid,r); } } void Update(int k) { if(seg[k].val>1) seg[k].area=line_y[seg[k].r]-line_y[seg[k].l]; //calculate area else if(seg[k].r-seg[k].l==1) seg[k].area=0; else seg[k].area=seg[2*k].area+seg[2*k+1].area; } void Insert(int k,int l,int r) { if(seg[k].r-seg[k].l==1) { seg[k].val++; Update(k); return ; } int mid=(seg[k].l+seg[k].r)/2; if(l<mid) Insert(k*2,l,r); if(r>mid) Insert(k*2+1,l,r); Update(k); } void Remove(int k,int l,int r) { if(seg[k].r-seg[k].l==1) { seg[k].val--; Update(k); return ; } int mid=(seg[k].l+seg[k].r)/2; if(l<mid) Remove(2*k,l,r); if(r>mid) Remove(2*k+1,l,r); Update(k); } void Add(double x1,double y1,double x2,double y2,int i) //add (x1,y1)-(x2,y2) line set. { int k=2*i; line[k].x=x1; line[k].y1=y1; line[k].y2=y2; line[k].s=1; line[k+1].x=x2; line[k+1].y1=y1; line[k+1].y2=y2; line[k+1].s=0; line_y[k]=y1; line_y[k+1]=y2; } void run() { //when input the cubes, use add() to add them. //then sort the array line and line_y. //in here, n is double of the number of cubes. //left and right. //after that, we delete the epactal lines in the set. //then insert the lines into segment tree. //let len is the new range of lines. n*=2; sort(line,line+n); sort(line_y,line_y+n); len=1; for(int i=1;i<n;i++) if(line_y[i]!=line_y[i-1]) line_y[len++]=line_y[i]; Init(1,0,len-1); sum=0.0; int l,r; //s=delta_x*delta_y for(int i=0;i<n-1;i++) { l=Read(line[i].y1); r=Read(line[i].y2); if(line[i].s) Insert(1,l,r); else Remove(1,l,r); sum+=seg[1].area*(line[i+1].x-line[i].x); } printf("%.2f/n",sum); } int main() { double x1,x2,y1,y2; int t; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); Add(x1,y1,x2,y2,i); } run(); } return 0; }

 

 

 

你可能感兴趣的:(数据结构,struct,delete,ini,input,insert)