链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255
中文题意就不用再说了。
这是赤裸裸的线扫描问题,唯一不同的就是求得面积是覆盖超过两次的面积的大小。其实就是求覆盖面积里面多一个变量来存储覆盖一次的长度(HDU 1542)。
这里有一个小小的坑点,要注意if语句判断的顺序。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 5 const int maxn=2018; 6 int n; 7 double x[maxn*2]; 8 9 struct Line 10 { 11 double x1,x2,y; 12 operator<(const Line &a)const 13 { 14 return y<a.y; 15 } 16 int flag; 17 }line[maxn*2]; 18 19 struct Trie 20 { 21 int l,r;///线段树的左右端点 22 double dl,dr;///左右端点的大小 23 double len1,len2;///覆盖一次与两次的长度 24 int cov;///被覆盖的次数 25 }a[maxn*4]; 26 27 void Get_Len(int id) 28 { 29 if(a[id].cov>0) 30 a[id].len1=a[id].dr-a[id].dl; 31 else if(a[id].l+1==a[id].r) 32 a[id].len1=0; 33 else 34 a[id].len1=a[id*2].len1+a[id*2+1].len1; 35 36 if(a[id].cov>1) 37 a[id].len2=a[id].dr-a[id].dl; 38 else if(a[id].l+1==a[id].r)///(①) 39 a[id].len2=0; 40 else if(a[id].cov==1)///(②) 41 ///① ②两个if语句交换了之后就是WA 42 ///先判断①就是防止②语句的id*2可能不存在 43 a[id].len2=a[id*2].len1+a[id*2+1].len1; 44 else 45 a[id].len2=a[id*2].len2+a[id*2+1].len2; 46 } 47 void Build(int id,int l,int r) 48 { 49 a[id].cov=0; 50 a[id].dl=x[l]; 51 a[id].dr=x[r]; 52 a[id].l=l; 53 a[id].r=r; 54 a[id].len1=0; 55 a[id].len2=0; 56 if(l+1==r) 57 return ; 58 int mid=(l+r)/2; 59 Build(id*2,l,mid); 60 Build(id*2+1,mid,r); 61 62 } 63 void Updata(int id,Line e) 64 { 65 if(a[id].dl==e.x1&&a[id].dr==e.x2) 66 { 67 a[id].cov+=e.flag; 68 Get_Len(id); 69 return ; 70 } 71 72 if(a[id*2].dr>=e.x2) 73 Updata(id*2,e); 74 else if(a[id*2+1].dl<=e.x1) 75 Updata(id*2+1,e); 76 else 77 { 78 Line tep=e; 79 tep.x2=a[id*2].dr; 80 Updata(id*2,tep); 81 82 tep=e; 83 tep.x1=a[id*2+1].dl; 84 Updata(id*2+1,tep); 85 } 86 Get_Len(id); 87 } 88 89 int main() 90 { 91 int t; 92 scanf("%d",&t); 93 while(t--) 94 { 95 scanf("%d",&n); 96 int cnt=0; 97 for(int i=1;i<=n;i++) 98 { 99 double x1,y1,x2,y2; 100 scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2); 101 cnt++; 102 line[cnt].x1=x1; 103 line[cnt].x2=x2; 104 line[cnt].y=y1; 105 line[cnt].flag=1; 106 x[cnt]=x1; 107 108 cnt++; 109 line[cnt].x1=x1; 110 line[cnt].x2=x2; 111 line[cnt].y=y2; 112 line[cnt].flag=-1; 113 x[cnt]=x2; 114 } 115 sort(x+1,x+1+cnt); 116 sort(line+1,line+1+cnt); 117 Build(1,1,cnt); 118 Updata(1,line[1]); 119 double ans=0; 120 for(int i=2;i<=cnt;i++) 121 { 122 123 ans+=a[1].len2*(line[i].y-line[i-1].y); 124 Updata(1,line[i]); 125 } 126 printf("%.2f\n",ans); 127 } 128 return 0; 129 }