李超线段树

李超线段树是一种用于在平面直角坐标系中,高效维护多个线段,并支持查询在某个横坐标 \(x\) 处,所有线段中纵坐标 \(y\) 的最大值(或最小值)的数据结构。
对于每个区间,维护完全在这个区间内的所有线段中, \(mid\) 处值最大(或最小)的线段。
插入线段时,像普通线段树一样将线段拆分成 \(\log n\) 个区间。对于每个区间,比较新线段与当前区间所保留线段在 \((mid)\) 处的取值。如果新线段在 \((mid)\) 处更优,则交换二者,并将被换下的线段继续向子区间递归插入。具体来说,若被换下的线段在左子区间(或右子区间)的某一端取值更优,则将其插入对应的子区间,以保证区间内始终保留在 \((mid)\) 处最优的线段。
这样 \(\log n\) 个拼成原区间的区间最多向下递归 \(\log n\) 层,插入时间复杂度 \(\mathcal{O}(\log^2n)\)
查询直接把路径上保留的区间在该点的值算出来,取 \(max\)(或 \(min\)),时间复杂度 \(\mathcal{O}(\log n)\)
放个模板题P4097 【模板】李超线段树 / [HEOI2013] Segment - 洛谷代码

#include<bits/stdc++.h>
using namespace std;
namespace IO{
    template<typename T>
    inline void read(T&x){
        x=0;char c=getchar();bool f=0;
        while(!isdigit(c)) c=='-'?f=1:0,c=getchar();
        while(isdigit(c)) x=x*10+c-'0',c=getchar();
        f?x=-x:0;
    }
    template<typename T>
    inline void write(T x){
        if(x==0){putchar('0');return ;}
        x<0?x=-x,putchar('-'):0;short st[50],top=0;
        while(x) st[++top]=x%10,x/=10;
        while(top) putchar(st[top--]+'0');
    }
    inline void read(char&c){c=getchar();while(isspace(c)) c=getchar();}
    inline void write(char c){putchar(c);}
    inline void read(string&s){s.clear();char c;read(c);while(!isspace(c)&&~c) s+=c,c=getchar();}
    inline void write(string s){for(int i=0,len=s.size();i<len;i++) putchar(s[i]);}
    inline void write(double x){printf("%lf",x);}
    template<typename T>inline void write(T*x){while(*x) putchar(*(x++));}
    template<typename T,typename...T2> inline void read(T&x,T2&...y){read(x),read(y...);}
    template<typename T,typename...T2> inline void write(const T x,const T2...y){write(x),putchar(' '),write(y...),sizeof...(y)==1?putchar('\n'):0;}
}using namespace IO;
const double eps=1e-5,inf=1e18;
struct Line{//y=kx+b;
    double k,b;
    int id;
    double js(double x){return x*k+b;}
    double js(int x){return x*k+b;}
};
bool equal(double a,double b){return abs(a-b)<eps;}
bool cmp(pair<double,int>a,pair<double,int>b){
    if(equal(b.first,a.first)) return b.second>a.second;
    return b.first>a.first;
}
template<int maxn>class Li_Chao_Segment_Tree{
private:
    struct Node_for_Li_Chao_Segment_Tree{Line x;}t[maxn*8+10];
    void insert(int u,int l,int r,int ll,int rr,Line x){
        if(l>rr||r<ll) return ;
        int mid=l+r>>1;
        if(ll<=l&&r<=rr){
            if(t[u].x.id==0){t[u].x=x;return ;}
            double z1=x.js(mid),z2=t[u].x.js(mid);
            if(z1>z2||equal(z1,z2)&&x.id<t[u].x.id) swap(x,t[u].x);
            if(l==r) return ;
            if(x.js(l)>t[u].x.js(l)) insert(u<<1,l,mid,ll,rr,x);
            else insert(u<<1|1,mid+1,r,ll,rr,x);
            return ;
        }
        if(l==r) return ;
        insert(u<<1,l,mid,ll,rr,x);insert(u<<1|1,mid+1,r,ll,rr,x);
    }
    pair<double,int>query(int u,int l,int r,int d){
        if(l>d||r<d) return {-inf,0};
        pair<double,int>nans={-inf,0};
        nans={t[u].x.js(d),-t[u].x.id};
        // write(nans.first,nans.second,"!!");
        if(l==r) return nans;
        int mid=l+r>>1;
        return max({query(u<<1,l,mid,d),query(u<<1|1,mid+1,r,d),nans},cmp);
    }
public:
    void insert(int l,int r,Line x){insert(1,1,maxn,l,r,x);}
    int query(int d){return -query(1,1,maxn,d).second;}
    void out(int u=1,int l=1,int r=maxn){
        write(u,l,r,t[u].x.id,"!");
        if(l==r) return ;
        int mid=l+r>>1;
        out(u<<1,l,mid),out(u<<1|1,mid+1,r);
    }
};
Li_Chao_Segment_Tree<40000>t;
signed main(){
    int n,ltans=0,cnt=0;read(n);
    for(int i=1;i<=n;i++){
        int op,x,y,xx,yy;
        read(op,x);
        x=(x+ltans-1+39989)%39989+1;
        if(op==0) write(ltans=t.query(x)),write("\n");
        else{
            read(y,xx,yy);
            y=(y+ltans-1+1000000000)%1000000000+1;
            xx=(xx+ltans-1+39989)%39989+1;
            yy=(yy+ltans-1+1000000000)%1000000000+1;
            Line nw;
            if(x==xx) nw.k=0,nw.b=max(1.0*y,1.0*yy);
            else nw.k=1.0*(y-yy)/(x-xx),nw.b=y-x*nw.k;
            nw.id=++cnt;
            t.insert(min(x,xx),max(xx,x),nw);
        }
        // if(i==2) t.out();
    }
    return 0;
}
/*
3
1 8 7 3 9
1 10 9 4 3
0 8
*/
posted @ 2025-12-04 22:42  Link-Cut_Trees  阅读(7)  评论(0)    收藏  举报