线段树+扫描线求矩阵面积并

本文介绍了如何使用段树和扫描线算法高效地计算多个垂直线段覆盖矩形区域的总面积。通过将线段排序并利用段树进行区间查询,实现了复杂度优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值