李超树

李超树,用来处理以下一类问题:

可以插入定义域任意的一次函数(即一个线段)。

给出 \(k\),询问与直线 \(x=k\) 相交的线段中,交点纵坐标最大的线段的纵坐标或编号。

一般与斜率优化 搭配使用

可以看这篇博客 讲述。

为什么要标记永久化?

首先这个标记是不能lazy的,因为两个线段标记相遇时对区间的不同位置影响不同,所以只能永久化了。

查询时为什么要把每个的线段都算?

在添加时吗,只会往交叉的一边递归,但另一边有时候也需要更新,但我们没有更新,此时将经过的所以线段都算就可以解决。

考虑李超线段树的本质是什么,实际是你有若干个函数,函数在 \(i\) 位置的取值是好计算的,且两两函数都满足只存在一个交点,那么你就能使用李超线段树来维护函数在任意位置取到的极值。

李超线段树最重要的大概就是他的 pushdown 了,所以这里给出一次函数的 pushdown:

db di(db k,db b,ll x){
	return k*x+b;
}
void pd(ll p,ll l,ll r,db k,db b){
	ll mid=(l+r)>>1;
	if(di(k,b,mid)>di(t[p].k,t[p].b,mid)) swap(k,t[p].k),swap(b,t[p].b);
	if(l==r)return;
	if(di(k,b,l)>di(t[p].k,t[p].b,l)){
		if(!lp) lp=bd();
		pd(lp,l,mid,k,b);
	}
	if(di(k,b,r)>di(t[p].k,t[p].b,r)){
		if(!rp) rp=bd();
		pd(rp,mid+1,r,k,b);
	}
}
posted @ 2026-04-11 16:20  kilees  阅读(29)  评论(0)    收藏  举报