1:段树+扫描线 矩形面积并:
struct seg
{
int a,b;
int len;
int cov; //被覆盖的次数
};
seg tree[maxn * 4];
void maketree(int a,int b,int k)
{
tree[k].a = a;
tree[k].b = b;
tree[k].len = 0;
tree[k].cov = 0;
if(a + 1 == b)
return;
int mid = (a+b)>>1;
maketree(a,mid,k<<1);
maketree(mid,b,k<<1|1);
}
inline void update_info(int k)
{
if(tree[k].cov == 0) //当且仅当当前线段未被覆盖时,其长度才==儿子的长度之和,注意叶子结点 不会执行到这里,不用考虑
tree[k].len = tree[k<<1].len + tree[k<<1|1].len;
}
void update(int c,int d,char flag,int k)
{
if(c <= tree[k].a && tree[k].b <= d)
{
if(flag == 1)
{
tree[k].len = tree[k].b - tree[k].a;
tree[k].cov ++;
}
else
{
tree[k].cov --;
if(tree[k].cov == 0) //注意..删除这条线段后,可能其儿子的线段还存在的..所以
{
if(tree[k].a + 1 == tree[k].b) //叶子结点
tree[k].len = 0;
else
tree[k].len = tree[k<<1].len + tree[k<<1|1].len; //非叶子结点
}
}
return;
}
if(c < tree[k<<1].b)
update(c,d,flag,k<<1);
if(d > tree[k<<1|1].a)
update(c,d,flag,k<<1|1);
update_info(k); //儿子被更新后,当当前线段的cov为0时,要更新当前结点的len
}
/ 垂直线段
struct VLine
{
int x,y1,y2;
char flag; //1: 入边, -1:出边
};
bool cmp(VLine vl1,VLine vl2)
{
return vl1.x < vl2.x;
}
VLine VL[maxn * 8];
int tail;
void Add(int x1,int y1,int x2,int y2)
{
if(x1 == x2 || y1 == y2) //注意要判断矩形是否合法..不合法的直接不用加入.没加这个WA N次..
return;
VL[tail].x = x1;
VL[tail].y1 = y1;
VL[tail].y2 = y2;
VL[tail].flag = 1;
tail++;
VL[tail].x = x2;
VL[tail].y1 = y1;
VL[tail].y2 = y2;
VL[tail].flag = -1;
tail++;
}
-------------------------------
sort(VLque,VLque+tail,cmp);
__int64 area = 0;
maketree(0,50000,1);
update(VL[0].y1,VL[0].y2,VL[0].flag,1); //单独处理第一条边
for(int i = 1; i<tail; i++)
{
area += __int64 ( VL[i].x - VL[i-1].x ) * tree[1].len;
update(VL[i].y1,VL[i].y2,VL[i].flag,1);
}
printf("%I64dn",area);
线段树+扫描线求矩阵面积并
最新推荐文章于 2021-02-17 18:54:30 发布