学习到线段树,然后有些题要求覆盖面积,据说用扫描线做,这算是我这类题的第一个吧
参考了好多资料,最后看的http://blog.csdn.net/youngyangyang04/article/details/7787693
勉强懂了些吧,最开始一直没理解到计算长度的时候t[index].l+1==t[index].r这里赋为0,后来想通了,原来是当val<=0的时候要删除当前边结点。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=311;
struct node
{
double x;
double y1;
double y2;
int flag;
bool operator <(const node &a)const
{
return x<a.x;
}
}p[maxn];
struct Tree
{
int l;
int r;
double ly;
double ry;
double len;
int val;
}t[maxn*2];
int n;
double py[maxn];
void Build(int L,int R,int index)
{
t[index].l=L;
t[index].r=R;
t[index].ly=py[L];
t[index].ry=py[R];
t[index].len=t[index].val=0;
if(L==R-1)
return;
int mid=(L+R)>>1;
Build(L,mid,index<<1);
Build(mid,R,index<<1|1);
}
void Callen(int index)
{
if(t[index].val>0)
t[index].len=t[index].ry-t[index].ly;
else if(t[index].l+1==t[index].r)
t[index].len=0;
else
t[index].len=t[index<<1].len+t[index<<1|1].len;
}
void Update(double y1,double y2,int val,int index)
{
if(t[index].ly==y1&&t[index].ry==y2)
{
t[index].val+=val;
Callen(index);
return;
}
if(y2<=t[index<<1].ry)
Update(y1,y2,val,index<<1);
else if(y1>=t[index<<1|1].ly)
Update(y1,y2,val,index<<1|1);
else
{
Update(y1,t[index<<1].ry,val,index<<1);
Update(t[index<<1|1].ly,y2,val,index<<1|1);
}
Callen(index);
}
int main()
{
int cas=1;
while(scanf("%d",&n)&&n)
{
int count=1;
for(int i=1;i<=n;i++)
{
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
p[count].x=x1;
p[count].y1=y1;
p[count].y2=y2;
p[count].flag=1;
py[count++]=y1;
p[count].x=x2;
p[count].y1=y1;
p[count].y2=y2;
p[count].flag=-1;
py[count++]=y2;
}
count--;
sort(p+1,p+count+1);
sort(py+1,py+count+1);
Build(1,count,1);
Update(p[1].y1,p[1].y2,p[1].flag,1);
double ans=0;
for(int i=2;i<=count;i++)
{
ans+=t[1].len*(p[i].x-p[i-1].x);
Update(p[i].y1,p[i].y2,p[i].flag,1);
}
printf("Test case #%d\n",cas++);
printf("Total explored area: %.2lf\n\n",ans);
}
return 0;
}