覆盖的面积(线段树+扫描线)

因为要求覆盖两次的面积,所以可以开二维表示被覆盖1次及以上和被覆盖两次及以上的面积。

主要在up更新上,如果当前区间被标记为一次,二次覆盖的面积就为其儿子面积之和,具体看代码吧。

  1 #include <iostream>

  2 #include<cstdio>

  3 #include<cstring>

  4 #include<algorithm>

  5 #include<stdlib.h>

  6 #include<vector>

  7 #include<cmath>

  8 #include<queue>

  9 #include<set>

 10 #include<map>

 11 using namespace std;

 12 #define N 4010

 13 #define LL long long

 14 #define INF 0xfffffff

 15 const double eps = 1e-8;

 16 const double pi = acos(-1.0);

 17 const double inf = ~0u>>2;

 18 map<double,int>f;

 19 double s[N<<2],res[N<<2];

 20 int fs[N<<2];

 21 double val[N],que[N];

 22 struct node

 23 {

 24     double x1,x2,y;

 25     int f;

 26     node(){}

 27     node(double x1,double x2,double y,int f):x1(x1),x2(x2),y(y),f(f){}

 28     bool operator < (const node &s) const

 29     {

 30         return y <s.y;

 31     }

 32 }p[N];

 33 void up(int w,int l,int r)

 34 {

 35     if(fs[w]>1)

 36     {

 37         s[w] = val[r+1]-val[l];

 38         res[w] = s[w];

 39     }

 40     else if(fs[w]==1)

 41     {

 42         if(l==r)

 43         s[w] = 0;

 44         else

 45         s[w] = res[w<<1]+res[w<<1|1];

 46         res[w] = val[r+1]-val[l];

 47     }

 48     else

 49     {

 50         if(l==r)

 51         {

 52             s[w] = 0;

 53             res[w] = 0;

 54         }

 55         else

 56         {

 57             s[w] = s[w<<1]+s[w<<1|1];

 58         res[w] = res[w<<1]+res[w<<1|1];

 59         }

 60     }

 61 }

 62 void build(int l,int r,int w)

 63 {

 64     fs[w] = 0;

 65     res[w] = s[w] = 0;

 66     if(l==r)

 67     {

 68         return ;

 69     }

 70     int m = (l+r)>>1;

 71     build(l,m,w<<1);

 72     build(m+1,r,w<<1|1);

 73     up(w,l,r);

 74 }

 75 void update(int a,int b,int d,int l,int r,int w)

 76 {

 77     if(a<=l&&b>=r)

 78     {

 79         fs[w]+=d;

 80         up(w,l,r);

 81         return ;

 82     }

 83     int m = (l+r)>>1;

 84     if(a<=m) update(a,b,d,l,m,w<<1);

 85     if(b>m) update(a,b,d,m+1,r,w<<1|1);

 86     up(w,l,r);

 87 }

 88 int main()

 89 {

 90     int t,i,n;

 91     scanf("%d",&t);

 92     while(t--)

 93     {

 94         scanf("%d",&n);

 95         f.clear();

 96         int g = 0;

 97         for(i = 1; i <=n ;i++)

 98         {

 99             double x1,x2,y1,y2;

100             scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);

101             p[++g] = node(x1,x2,y1,1);

102             que[g] = x1;

103             p[++g] = node(x1,x2,y2,-1);

104             que[g] = x2;

105         }

106         sort(p+1,p+g+1);

107         sort(que+1,que+g+1);

108         int o = 0;

109         f[que[1]] = ++o;

110         val[o] = que[1];

111         for(i = 2; i <= g; i++)

112         {

113             if(fabs(que[i]-que[i-1])>0)

114             {

115                 f[que[i]] = ++o;

116                 val[o] = que[i];

117             }

118         }

119         double ans = 0;

120         build(1,o-1,1);

121         for(i = 1; i < g ; i++)

122         {

123             int l = f[p[i].x1];

124             int r = f[p[i].x2]-1;

125             if(l<=r)

126             {

127                 update(l,r,p[i].f,1,o-1,1);

128             }

129             double sum = s[1]*(p[i+1].y-p[i].y);

130            // cout<<sum<<endl;

131             ans+=sum;

132         }

133         printf("%.2f\n",ans);

134     }

135     return 0;

136 }
View Code

 

 

你可能感兴趣的:(线段树)