尽人事,听天命。|

Jerrycyx

园龄:2年9个月粉丝:2关注:1

📂闲话
🔖闲话
2025-03-06 15:59阅读: 3评论: 0推荐: 0

2025.3.1 闲话:扫描线线段树空间问题

先看正常的线段树代码片段:

void add(int l,int r,int x,int p=1)
{
if(l<=tree[p].l&&tree[p].r<=r)
{
tree[p].dat+=x*tree[p].get_len();
tree[p].lazy+=x;
return;
}
spread(p)
int mid=tree[p].get_mid();
if(l<=mid) add(l,r,x,p<<1);
if(r>mid) add(l,r,x,p<<1|1);
update(p);
return;
}

可以看到,对于叶节点,我们不会执行 update(p),因为只要进入了叶节点,那么开头的判断条件一定成立,直接 return 了。

在这种情况下,线段树大小是 \(4n\)


再来看扫描线所用线段树的代码片段:

inline void update(int p)
{
if(tree[p].cnt) tree[p].len=from[tree[p].r+1]-from[tree[p].l];
else tree[p].len=tree[p<<1].len+tree[p<<1|1].len;
return;
}
void Add(int l,int r,int x,int p)
{
if(l<=tree[p].l&&tree[p].r<=r)
tree[p].cnt+=x;
else
{
int mid=tree[p].l+tree[p].r>>1;
if(l<=mid) Add(l,r,x,p<<1);
if(r>mid) Add(l,r,x,p<<1|1);
}
update(p);
return;
}

可以看到,在这种情况下即使是叶节点也会执行 update 函数,而 update 可能访问当前节点的子节点(即使叶节点的子节点为空)。

普通线段树的叶节点最大编号为 \(4n\),这里叶节点还要访问子节点,那么这里就不得不开 \(8n\) 的空间(或者可以对叶节点特判)。

\(n\) 表示元素数量,而扫描线中线段树所存元素数量为两倍矩形数量,所以前面的 \(n\) 其实是 \(2n\)因此扫描线线段树空间应开 \(16n\)(真吓人)。

posted @   Jerrycyx  阅读(3)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起