其他分享
首页 > 其他分享> > 李超线段树

李超线段树

作者:互联网

解决多线段单点最值问题。

模板题

浅略的说一下。

每个区间存储位于当前区间中的值最大的线段。每次插入新线段,如果当前区间没有存储线段,就直接插在这里,否则分类讨论一下,如果某一个子区间的最优线段必定是当前线段,这个子区间就不用处理了。而对于另一个有不确定因素的,我们把当前的不优线段下传即可。具体实现看代码,本质上是标记永久化,所以查询的时候直接对于每个点都更新一下答案就好。

#include<bits/stdc++.h>
#define ll long long
#define db double 
#define filein(a) freopen(#a".in","r",stdin)
#define fileot(a) freopen(#a".out","w",stdout)
#define Better_IO true
namespace IO{
    #if Better_IO
        char buf[(1<<20)+3],*p1(buf),*p2(buf);
        const int lim=1<<20;
        inline char gc(){
            if(p1==p2) p2=(p1=buf)+fread(buf,1,lim,stdin);
            return p1==p2?EOF:*p1++;
        }
        #define pc putchar
    #else
        #define gc getchar
        #define pc putchar
    #endif
    inline bool blank(char c){
        return c=='\t' or c=='\n' or c=='\r' or c==' ' or c==EOF;
    }
    inline void gs(char *s){
        char ch=gc();
        while(blank(ch) ) ch=gc();
        while(!blank(ch) ) {*s++=ch;ch=gc();}
        *s=0;
    }
    inline void ps(char *s){
        while(*s!=0) {pc(*s++);}
    }
    template<class T>
    inline void read(T &s){
        s=0;char ch=gc();bool f=0;
        while(ch<'0'||'9'<ch) {if(ch=='-') f=1;ch=gc();}
        while('0'<=ch&&ch<='9') {s=s*10+(ch^48);ch=gc();}
        if(ch=='.'){
            db p=0.1;ch=gc();
            while('0'<=ch&&ch<='9') {s=s+p*(ch^48);ch=gc();p*=0.1;}
        }
        s=f?-s:s;
    }
    template<class T,class ...A>
    inline void read(T &s,A &...a){
        read(s);read(a...);
    }
};
using IO::gs;
using IO::ps;
using IO::read;
using IO::gc;
const int N=1e5+3;
int n;
const db inf=1e9;
int tot;
struct line{
    db k,b;
}p[N];
inline line change(int sx,int sy,int fx,int fy){
    db k,b;
    if(sx==fx){
        k=0;
        b=std::max(sy,fy);
    }else{
        k=(db)(fy-sy)/(db)(fx-sx);
        b=sy-(db)k*sx;
    }
    return (line){k,b};
}
#define pr std::pair<db,int>
inline pr max(pr x,pr y){
    if(x.first<y.first) return y;
    else if(x.first>y.first) return x;
    return x.second<y.second?x:y;
} 
inline db calc(int id,int x){
    return (p[id].k*x+p[id].b);
}
const int N2=39989+3;
struct SegTree{
    #define lc(x) (x<<1)
    #define rc(x) (x<<1|1)
    struct node{
        int l,r,mid;
        int id;
    }t[N2<<2];
    inline void build(int x,int l,int r){
        t[x].l=l;t[x].r=r;t[x].mid=(l+r)>>1;
        t[x].id=0;
        if(l==r){
            return;
        }
        build(lc(x),l,t[x].mid);
        build(rc(x),t[x].mid+1,r);
    }
    inline void modify(int x,int l,int r,int id){
        if(t[x].l>r or t[x].r<l) return;
        db val1=calc(t[x].id,t[x].mid),val2=calc(id,t[x].mid);
        if(l<=t[x].l and t[x].r<=r){
            if(!t[x].id){
                t[x].id=id;
                return;
            }
            if(t[x].l==t[x].r){
                if(val1<val2) t[x].id=id;
                else if(val1==val2) t[x].id=std::min(id,t[x].id);
                return;
            }
            if(p[t[x].id].k<p[id].k){
                if(val1<val2){
                    modify(lc(x),l,r,t[x].id);
                }else{
                    modify(rc(x),l,r,id);
                }
            }else if(p[t[x].id].k>p[id].k){
                if(val1<val2){
                    modify(rc(x),l,r,t[x].id);
                }else{
                    modify(lc(x),l,r,id);
                }
            }
            if(val1<val2) t[x].id=id;
            else if(val1==val2) t[x].id=std::min(id,t[x].id);
            return;
        }
        modify(lc(x),l,r,id);
        modify(rc(x),l,r,id);
    }
    inline pr query(int x,int k){
        db res=calc(t[x].id,k);
        pr ans={res,t[x].id};
        if(t[x].l==t[x].r) return ans;
        if(k<=t[x].mid) ans=max(ans,query(lc(x),k) );
        if(t[x].mid+1<=k) ans=max(ans,query(rc(x),k) );
        return ans;
    }
    #undef lc
    #undef rc
}t;
int la;
int main(){
    filein(a);fileot(a);
    read(n);
    p[0]={-1e9,-1e9};
    t.build(1,1,39989);
    for(int i=1;i<=n;++i){
        int op;
        read(op);
        if(op==0){
            int x;
            read(x);
            x=(x+la-1)%39989+1;
            printf("%d\n",la=t.query(1,x).second);
        }
        if(op==1){
            int sx,sy,fx,fy;
            read(sx,sy,fx,fy);
            sx=(sx+la-1)%39989+1;
            sy=(sy+la-1)%(int)1e9+1;
            fx=(fx+la-1)%39989+1;
            fy=(fy+la-1)%(int)1e9+1;
            if(sx>fx){
                std::swap(sx,fx);
                std::swap(sy,fy);
            }
            p[++tot]=change(sx,sy,fx,fy);
            t.modify(1,sx,fx,tot);
        }
    }
    return 0;
}

标签:sx,int,线段,db,李超,IO,define
来源: https://www.cnblogs.com/cbdsopa/p/16212416.html