李超树
李超树,用来处理以下一类问题:
可以插入定义域任意的一次函数(即一个线段)。
给出 \(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);
}
}

浙公网安备 33010602011771号