扫描线处理矩形覆盖过至少两次的区域的面积.
把callen函数的修改一下即可
data[k].len表示被覆盖的长度
data[k].sum表示被覆盖两次以上的长度
#include "stdio.h"
#include "string.h"
#include "algorithm"
#include "math.h"
using namespace std;
struct Mark
{
double x,ml,mr;
int flag;
}mark[50010];
struct Data
{
double ml,mr,s,len,sum;
int l,r,lazy;
}data[50010];
double y[50010];
bool cmp(Mark a,Mark b)
{
return a.x-b.x<0.0000001;
}
void build(int l,int r,int k)
{
int mid;
data[k].l=l;
data[k].r=r;
data[k].ml=y[l];
data[k].mr=y[r];
data[k].s=data[k].lazy=0;
data[k].len=data[k].sum=0;
if (l+1==r) return ;
mid=(l+r)/2;
build(l,mid,k*2);
build(mid,r,k*2+1);
}
void callen(int k)
{
if (data[k].s>1)
{
data[k].len=data[k].mr-data[k].ml;
data[k].sum=data[k].mr-data[k].ml;
}
else
if (data[k].s==1)
{
data[k].len=data[k].mr-data[k].ml;
if (data[k].l+1==data[k].r) data[k].sum=0;
else
data[k].sum=data[k*2].len+data[k*2+1].len;
}
else
if (data[k].l+1==data[k].r)
{
data[k].len=0;
data[k].sum=0;
}
else
{
data[k].len=data[k*2].len+data[k*2+1].len;
data[k].sum=data[k*2].sum+data[k*2+1].sum;
}
}
void updata(int k,Mark b)
{
if (data[k].ml==b.ml && data[k].mr==b.mr)
{
data[k].s+=b.flag;
callen(k);
return ;
}
if (b.mr<=data[k*2].mr) updata(k*2,b);
else
if (b.ml>=data[k*2+1].ml) updata(k*2+1,b);
else
{
Mark c;
c=b;
c.mr=data[k*2].mr;
updata(k*2,c);
c=b;
c.ml=data[k*2+1].ml;
updata(k*2+1,c);
}
callen(k);
}
int main()
{
int Case,n,i,len,cnt;
double sum,x1,y1,x2,y2;
scanf("%d",&Case);
while (Case--)
{
cnt=0;
scanf("%d",&n);
for (i=0;i<n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
mark[cnt].x=x1;
mark[cnt].ml=y1;
mark[cnt].mr=y2;
mark[cnt].flag=1;
y[cnt++]=y1;
mark[cnt].x=x2;
mark[cnt].ml=y1;
mark[cnt].mr=y2;
mark[cnt].flag=-1;
y[cnt++]=y2;
}
sort(mark,mark+cnt,cmp);
sort(y,y+cnt);
len=1;
for (i=1;i<cnt;i++)
if (y[i]!=y[i-1])
{
y[len++]=y[i];
}
len--;
build(0,len,1);
sum=0;
updata(1,mark[0]);
for (i=1;i<cnt;i++)
{
sum+=data[1].sum*(mark[i].x-mark[i-1].x);
updata(1,mark[i]);
}
printf("%.2lf\n",sum);
}
return 0;
}
原文:http://blog.csdn.net/u011932355/article/details/44538661