李超线段树

单调栈/单调队列确实强势,但我不愿意动脑子。

原理

我们以模板题为例讲解李超线段树工作原理。
首先我们有一个基于值域的线段树。
称一个线段在区间 \([l,r]\) 中最优当且仅当该线段完全覆盖 \([l,r]\) 且在 \(mid\) 处的值为所有线段最大。
线段树上每个节点保存对应区间的最优线段。注意:区间的线段不能保证对于区间内所有点都取到最优。
考虑在一个区间插入一个线段 \(f\),若原区间有最优线段,设其为 \(f'\)

  • 若区间内原本没有线段,则直接令 \(f\) 成为最优线段;

  • \(f\) 完全位于 \(f'\) 上方(即“\(f\) 严格优于 \(f'\)”),直接替换掉;

  • 反之,\(f\) 不可能再成为最优线段,停止递归;

  • \(f\) 部分优于 \(f'\),则二者交点必然在区间内。按区间 \(mid\) 分开,则此时必然是:

    • 一个子区间内存在“严格优于”的关系;

    • 另一个子区间内是二者交点。递归更新。

对于第 3 种情况,不是区间最优线段的线段也有可能成为这个区间的答案。

单次查询操作时间复杂度 \(O(\log n)\),全局修改时间复杂度 \(O(\log n)\),区间修改时间复杂度 \(O(\log^2n)\)。李超线段树的常数较小。

code

template<typename T>
inline T Abs(const T &x){return x<0?-x:x;}
constexpr int N=1e5+10;
constexpr double eps=1e-9;
struct line{
    double k,b;
    int id;
    inline double Y(int x){return x*k+b;}
};
struct segmenttree{
    bool flag;
    line L;
}tree[N<<2];
#define ls (u<<1)
#define rs (u<<1|1)
void modify(int u,int l,int r,int x,int y,line p){
    if(x<=l&&y>=r){
        double ly1=tree[u].L.Y(l),ry1=tree[u].L.Y(r);
        double ly2=p.Y(l),ry2=p.Y(r);
        if(!tree[u].flag) tree[u].L=p,tree[u].flag=1;
        else if(ly2-ly1>eps&&ry2-ry1>eps) tree[u].L=p;
        else if(ly2-ly1>eps||ry2-ry1>eps){
            int mid=(l+r)>>1;
            double midy1=tree[u].L.Y(mid);
            double midy2=p.Y(mid);
            if(midy2-midy1>eps) swap(tree[u].L,p);
            if(p.Y(l)>tree[u].L.Y(l)) modify(ls,l,mid,x,y,p);
            else modify(rs,mid+1,r,x,y,p);
        }
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid) modify(ls,l,mid,x,y,p);
    if(y>mid) modify(rs,mid+1,r,x,y,p);
}
struct Res{double y;int id;};
Res query(int u,int l,int r,int x){
    Res res={tree[u].L.Y(x),tree[u].L.id};
    if(l==r) return res;
    int mid=(l+r)>>1;
    if(x<=mid){
        Res resl=query(ls,l,mid,x);
        if(resl.y>res.y||(Abs(resl.y-res.y)<eps&&resl.id<res.id))
            res=resl;
    }
    else{
        Res resr=query(rs,mid+1,r,x);
        if(resr.y>res.y||(Abs(resr.y-res.y)<eps&&resr.id<res.id))
            res=resr;
    }
    return res;
}
posted @ 2025-08-09 17:06  headless_piston  阅读(26)  评论(0)    收藏  举报