矩形面积并
线段树-扫描线裸题
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h>
2 #include<string.h>
3 #include<algorithm>
4 #include<math.h>
5 using namespace std;
6 const int maxm=2e3+5;
7 const double eps=1e-5;
8
9 struct seg{
10 double x,y1,y2;
11 int c;
12 bool operator < (const seg a)const{
13 return x<a.x;
14 }
15 }s[maxm];
16
17 double y[maxm];
18 double st[maxm<<2],st2[maxm<<2];
19 int cov[maxm<<2];
20
21 void pushup(int o,int l,int r){
22 if(cov[o]>1){
23 st[o]=st2[o]=y[r]-y[l];
24 }
25 else if(cov[o]==1){
26 st[o]=y[r]-y[l];
27 if(l+1==r)st2[o]=0;
28 else st2[o]=st[o<<1]+st[o<<1|1];
29 }
30 else{
31 if(l+1==r)st[o]=st2[o]=0;
32 else{
33 st[o]=st[o<<1]+st[o<<1|1];
34 st2[o]=st2[o<<1]+st2[o<<1|1];
35 }
36 }
37 }
38
39 void update(int o,int l,int r,seg a){
40 if(y[l]>=a.y1&&y[r]<=a.y2){
41 cov[o]+=a.c;
42 pushup(o,l,r);
43 return;
44 }
45 if(l+1==r)return;
46 int m=l+((r-l)>>1);
47 if(a.y1<=y[m])update(o<<1,l,m,a);
48 if(a.y2>y[m])update(o<<1|1,m,r,a);
49 pushup(o,l,r);
50 }
51
52 int main(){
53 int T;
54 scanf("%d",&T);
55 while(T--){
56 int n;
57 scanf("%d",&n);
58 memset(st,0,sizeof(st));
59 memset(cov,0,sizeof(cov));
60 memset(st2,0,sizeof(st2));
61 for(int i=1;i<=n;++i){
62 double x1,y1,x2,y2;
63 scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
64 /* s[2*i-1].x=x1;
65 s[2*i].x=x2;
66 s[2*i-1].y1=y1;
67 s[2*i].y1=y1;
68 s[2*i-1].y2=y2;
69 s[2*i].y2=y2;
70 s[2*i-1].c=1;
71 s[2*i].c=-1;
72 y[2*i-1]=y1;
73 y[2*i]=y2;*/
74 s[2*i-1].x=x1;s[2*i-1].y1=y1;s[2*i-1].y2=y2;s[2*i-1].c=1;
75 y[2*i-1]=y1;
76 s[2*i].x=x2;s[2*i].y1=y1;s[2*i].y2=y2;s[2*i].c=-1;
77 y[2*i]=y2;
78 }
79 sort(y+1,y+2*n+1);
80 sort(s+1,s+2*n+1);
81 /* int cnt=1;
82 for(int i=2;i<=2*n;++i){
83 if(y[i]!=y[i-1])y[++cnt]=y[i];
84 }*/
85 int cnt=2*n;
86 double ans=0;
87 update(1,1,cnt,s[1]);
88 for(int i=2;i<=2*n;++i){
89 ans+=st2[1]*(s[i].x-s[i-1].x);
90 update(1,1,cnt,s[i]);
91 }
92 printf("%.2lf\n",ans);
93 }
94 return 0;
95 }