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

时间:2022-02-04 21:19:44

http://acm.hdu.edu.cn/showproblem.php?pid=1255

典型线段树辅助扫描线,顾名思义扫描线就是相当于yy出一条直线从左到右(也可以从上到下)扫描过去,此时先将所有的横坐标和纵坐标排序

因为是从左到右扫描,那么横坐标应该离散化一下

当扫描线依次扫描的时候,依次扫描到的纵区间在线段树中查找,依据是上边还是下边记录,上边就是-1,下边就是+1,

如果某区间记录值为0的时候,代表没有被覆盖,为1的时候代表覆盖一次,为2代表覆盖两次(不会出现为负数的情况)

最后将依次扫描的覆盖两次的纵区间长度乘以以此的横坐标的和就行

所以http://acm.hdu.edu.cn/search.php?action=listproblem hdu1542 就在稍微改改这题的代码就行了

code

 #include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct node{
double x,y1,y2;
double flag;
};
node num[];
double a[];
bool cmp(node q,node w){return q.x<w.x;}
struct point {
int l,r,mark;
double lf,rf;
double once; //覆盖一次
double twice;//覆盖两次
};
point tree[*];
void build(int i,int left,int right)
{
tree[i].l=left,tree[i].r=right;
tree[i].once=tree[i].twice=;
tree[i].lf=a[left];
tree[i].rf=a[right];
if (left+==right) return ;
int mid=(left+right)/;
build(i*,left,mid);
build(i*+,mid,right);
}
void find(int i)
{
if (tree[i].mark>=)
{
tree[i].twice=tree[i].once=tree[i].rf-tree[i].lf;
return;
}
else if (tree[i].mark==)
{
tree[i].once=tree[i].rf-tree[i].lf;
if (tree[i].l+==tree[i].r) tree[i].twice=;
else tree[i].twice=tree[i*].once+tree[i*+].once;
}
else
{
if(tree[i].l+==tree[i].r)
tree[i].once=tree[i].twice=;
else
{
tree[i].once=tree[i*].once+tree[i*+].once;
tree[i].twice=tree[i*].twice+tree[i*+].twice;
}
}
}
void update(int i,node g)
{
//printf("***%d***\n",i);
if (g.y1==tree[i].lf&&g.y2==tree[i].rf)
{
tree[i].mark+=g.flag;
find(i); //更新区间
return ;
}
if (g.y2<=tree[i*].rf) update(i*,g);
else if (g.y1>=tree[i*+].lf) update(i*+,g);
else
{
node temp=g;
temp.y2=tree[i*].rf;
update(i*,temp);
temp=g;
temp.y1=tree[i*+].lf;
update(i*+,temp);
}
find(i);
}
int main()
{
int t,n,i,k;
double x1,x2,y1,y2,ans;
while (~scanf("%d",&k))
{
while (k--)
{
scanf("%d",&n);
t=;
while (n--)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
num[t].x=x1,num[t].y1=y1,num[t].y2=y2;
num[t].flag=;a[t]=y1;
t++;
num[t].x=x2,num[t].y1=y1,num[t].y2=y2;
num[t].flag=-;a[t]=y2;
t++;
}
sort(num+,num+t,cmp);
sort(a+,a+t);
ans=;
build(,,t-);
//printf("-1\n");
update(,num[]);
for (i=;i<t;i++)
{
ans+=tree[].twice*(num[i].x-num[i-].x);
update(,num[i]);
}
printf("%.2lf\n",ans);
}
}
return ;
}