线段树+扫描线求矩形面积的并
POJ 1151 Atlantis(线段树+扫描线)
参考博客https://blog.csdn.net/lwt36/article/details/48908031
上面博客的原理讲解非常清楚
在这我只对代码的模板分层讲解
一些基础的
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cmath>
#define lson rt<<1,left,mid
#define rson rt<<1|1,mid,right
#define eps 1e-8
using namespace std;
const int maxn = 222;
//线段树
struct node{
double len;
int cover;
}tree[maxn << 2];
线段树中len 是覆盖标记的长度,也就是扫描线扫过后的所有覆盖的长度
//离散化 double X[maxn]; int N;
以上是离散化的数组,因为x是浮点值,所以先映射到一个数组里,然后排序————从小到大
再利用一下代码
sort(X,X+N); int tn = unique(X,X+N) - X;
build(1,0,tn-1);
得到不同x的离散范围
这样就可以建树了
struct edge{
double x1,x2,y;
int flag;
}e[maxn<<2];
bool cmp(edge a,edge b)
{
if(a.y != b.y)return a.y < b.y;
else return a.flag > b.flag;
}
int cnt;
void add(double x1,double x2,double y,double xx,int flag)
{
e[cnt].x1 = x1;
e[cnt].x2 = x2;
e[cnt].y = y;
e[cnt].flag = flag;
X[N++] = xx;
cnt++;
}
void init()
{
cnt = 0;
N = 0;
}
以上是对边的存储,排序,加边,和整体的初始化操作
接下来我们建树:主要是初始化len和cover的值
void build(int rt,int left,int right)
{
tree[rt].len = 0.0;
tree[rt].cover = 0;
if(left + 1 == right)return;
int mid = (left + right) >> 1;
build(lson);
build(rson);
}
然后是扫描线更新,进本的更新,比较时利用离散化时的映射进行比较更新,找到区间更新cover,没有找到继续向下,知道叶子节点
中间顺便进行pushup向上维护
void updata(int rt,int left,int right,double x1,double x2,int v)
{
if(Equal(X[left],x1)&&Equal(X[right],x2))
{
tree[rt].cover += v;
}
if(left + 1 < right)
{
int mid = (left + right) >> 1;
if(x2 <= X[mid]+eps)
updata(lson,x1,x2,v);
else if(x1 >= X[mid] - eps)
updata(rson,x1,x2,v);
else
{
updata(lson,x1,X[mid],v);
updata(rson,X[mid],x2,v);
}
}
pup(rt,left,right);
}
维护应该比较好懂
bool Equal(double x,double y)
{
return abs(x-y) <= eps;
}
void pup(int rt,int left,int right)
{
if(tree[rt].cover)
tree[rt].len = X[right] - X[left];
else if(left + 1 == right)
tree[rt].len = 0.0;
else
tree[rt].len = tree[rt<<1].len + tree[rt<<1|1].len;
}
到此就差不多了
int main()
{
int cas = 1;
int n;
double x1,y1,x2,y2;
while(~scanf("%d",&n),n)
{
init();
for(int i = 1;i <= n;++i)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
add(x1,x2,y1,x1,1);
add(x1,x2,y2,x2,0);
}
sort(e,e+cnt,cmp);
//从小到大的离散化,把值都映射到了1 - N
sort(X,X+N);
int tn = unique(X,X+N) - X;
build(1,0,tn-1);
double ans = 0.0;
double length = 0.0;
for(int i = 0;i < cnt;i++)
{
if(e[i].flag == 1)
updata(1,0,tn-1,e[i].x1,e[i].x2,1);
else
updata(1,0,tn-1,e[i].x1,e[i].x2,-1);
if(i != 0)
ans += length * (e[i].y - e[i-1].y);
length = tree[1].len;
}
printf("Test case #%d\n",cas++);
printf("Total explored area: %.2f\n\n",ans);
}
return 0;
}

浙公网安备 33010602011771号