POJ1151-扫面线+线段树+离散化//入门题

时间:2022-09-01 19:37:52

比较水的入门题

记录矩形竖边的x坐标,离散化排序。以被标记的边建树。

扫描线段树,查询线段树内被标记的边。遇到矩形的右边就删除此边

每一段的面积是查询结果乘边的横坐标之差,求和就是答案

 #include <cstdio>
#include <cstring>
#include <algorithm> using namespace std;
const int maxn = ;
int N,num,kase;
double savey[maxn*]; struct line{
double x,y1,y2;
int flag;
bool operator < (const struct line &t) const {return x < t.x;}
}Line[maxn]; struct Node{
int l,r;
double dl,dr;
double len;
int flag;
}SegTree[maxn*]; void Build(int i,int l,int r)
{
SegTree[i].l = l;
SegTree[i].r = r;
SegTree[i].flag = SegTree[i].len = ;
SegTree[i].dl = savey[l];
SegTree[i].dr = savey[r];
if(l + == r) return;
int mid = (l+r)>>;
Build(i<<,l,mid);
Build(i<<|,mid,r);
} void getlen(int t)
{
if(SegTree[t].flag > )
{
SegTree[t].len = SegTree[t].dr - SegTree[t].dl;
return ;
}
if(SegTree[t].l+ == SegTree[t].r) SegTree[t].len = ;
else SegTree[t].len = SegTree[t<<].len + SegTree[t<<|].len;
} void Update(int i,line e)
{
if(e.y1 == SegTree[i].dl && e.y2 == SegTree[i].dr)
{
SegTree[i].flag += e.flag;
getlen(i);
return;
}
if(e.y2 <= SegTree[i<<].dr) Update(i<<,e);
else if(e.y1 >= SegTree[i<<|].dl) Update(i<<|,e);
else
{
line temp = e;
temp.y2 = SegTree[i<<].dr;
Update(i<<,temp);
temp = e;
temp.y1 = SegTree[i<<|].dl;
Update(i<<|,temp);
}
getlen(i);
} int main()
{
while(~scanf("%d",&N) && N)
{
kase++;
num=;
double x1,x2,y1,y2;
for(int i=;i<=N;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
Line[num].x = x1;
Line[num].y1 = y1;
Line[num].y2 = y2;
Line[num].flag = ;
savey[num++]=y1;
Line[num].x = x2;
Line[num].y1 = y1;
Line[num].y2 = y2;
Line[num].flag = -;
savey[num++] = y2;
}
sort(Line+,Line+num);
sort(savey+,savey+num);
Build(,,num-);
Update(,Line[]);
double ans = ;
for(int i=;i<num;i++)
{
//printf("%f %f\n",SegTree[1].len,Line[i].x-Line[i-1].x);
ans += SegTree[].len * (Line[i].x - Line[i-].x);
Update(,Line[i]);
}
printf("Test case #%d\n",kase);
printf("Total explored area: %.2f\n\n",ans);
}
return ;
}