你会写李超树吗?

P4097 【模板】李超线段树 / [HEOI2013] Segment

do_while_true @ 2022-06-26 23:03:31

今年的早些时候,年轻的 dwt(do_while_true) 正照常水群。

他看见 LA 群里强大的 George1123 正在吐槽早些时候写的臃肿题解,举了李超树的例子。

dwt 定睛一看,怎么李超树还有如此简洁的写法?他翻了 oi-wiki,翻了洛谷题解区,竟然都是 dwt 年少懵懂时所写的巨型分类讨论:

举例(来自我 21 年 4 月的提交记录):

void modify(int x, int cl, int cr, int l, int r, int u) {
    int v = tree[x].s, mid = (cl + cr) >> 1;
    if(r < cl || cr < l) return ;
    ld yu = calc(u, mid), yv = calc(v, mid);
    if(l <= cl && cr <= r) {
        if(cl == cr) {
            if(yu > yv) tree[x].s = u;
            return ;
        }
        if(li[v].k < li[u].k) {
            if(yu > yv) {
                tree[x].s = u;
                modify(ls, cl, mid, l, r, v);
            }
            else modify(rs, mid+1, cr, l, r, u);
        }
        else if(li[v].k > li[u].k) {
            if(yu > yv) {
                tree[x].s = u;
                modify(rs, mid+1, cr, l, r, v);
            }
            else modify(ls, cl, mid, l, r, u);
        }
        else if(li[u].b > li[v].b) tree[x].s = u;
        return ;
    }
    modify(ls, cl, mid, l, r, u);
    modify(rs, mid+1, cr, l, r, u);
}

他从未发现李超树竟然如此好写,于是费尽千辛万苦学会了李超树的简洁写法,现在它已经全面上线 oi-wiki,欢迎大家来学习和交流!


by NujObIuc @ 2022-06-26 23:11:17

@do_while_true 我感觉 panyf 的李超树代码是我最喜欢的,短小而精悍!

https://www.luogu.com.cn/blog/221955/solution-cf1175g


by do_while_true @ 2022-06-26 23:13:44

@ZCPB 其实你仔细看看,oi-wiki中的示例代码和 panyf 写的差不多,只不过他是全局插入(插入直线)所以少了一个函数!


by do_while_true @ 2022-06-26 23:15:01

他的代码压行稍微多一点,逻辑上是一样的?


by NujObIuc @ 2022-06-26 23:15:56

@do_while_true 道理都一样,但是 panyf 我感觉是迄今为止我见过最短的,感觉给人看起来非常的舒适。


by MC小萌新 @ 2022-06-26 23:18:03

我之前就照着 oiwiki 学的,代码和它差不多长/qd


by wkywkywky @ 2022-06-26 23:21:29

然而这并不巨型(


by 听取MLE声一片 @ 2022-06-26 23:22:08

巨型


by wkywkywky @ 2022-06-26 23:23:00

wky的分讨写法

void update(int rt,int ul,int ur,d uk,d ub,int uid){
  int l=tr[rt].l,r=tr[rt].r;
  int mid=(l+r)>>1;
  if(ul<=l&&r<=ur){
    d ue=((d)r-(d)l)*uk+ub;
    d te=((d)r-(d)l)*tr[rt].k+tr[rt].b;
    if(tr[rt].f==0){
      tr[rt].f=1;
      tr[rt].k=uk;tr[rt].b=ub;tr[rt].id=uid;
    }
    else {
      if(ub-tr[rt].b>eps&&ue-te>eps){
        tr[rt].k=uk;tr[rt].b=ub;tr[rt].id=uid;
      }
      else {
        if(ub-tr[rt].b<-eps&&ue-te<-eps)return;
        if(ub-tr[rt].b<-eps&&abs(ue-te)<eps)return;
        if(abs(ub-tr[rt].b)<eps&&ue-te<-eps)return;
        else {
          d um=((d)mid-(d)l)*uk+ub;
          d tm=((d)mid-(d)l)*tr[rt].k+tr[rt].b;
          if(ub-tr[rt].b>eps){
            if(um-tm>eps){
              update(rt*2+1,mid+1,r,tr[rt].k,tm+tr[rt].k,tr[rt].id);
              tr[rt].k=uk;tr[rt].b=ub;tr[rt].id=uid;
            }
            else {
              update(rt*2,ul,mid,uk,ub,uid);
            }
          }
          else {
            if(um-tm>eps){
              update(rt*2,l,mid,tr[rt].k,tr[rt].b,tr[rt].id);
              tr[rt].k=uk;tr[rt].b=ub;tr[rt].id=uid;
            }
            else {
              update(rt*2+1,mid+1,ur,uk,um+uk,uid);
            }
          }
        }
      }
    }
    return;
  }
  if(ul<=mid)update(rt*2,ul,ur,uk,ub,uid);
  if(ur>mid){
    if(ul>mid)update(rt*2+1,ul,ur,uk,ub,uid);
    else update(rt*2+1,mid+1,ur,uk,ub+((d)mid+(d)1-(d)ul)*uk,uid);
  }
}

by wkywkywky @ 2022-06-26 23:25:45

什么叫重工业啊(战术后仰)


by hellomath @ 2022-06-26 23:26:01

我的:

struct line { 
    ll k, b;
    ll operator () (ll x) { return k * x + b; }
} t[maxn << 2];

void ins(int k, int l, int r, line a) {
    if (t[k](mid) < a(mid)) swap(t[k], a);
    if (l == r) return;
    t[k].k > a.k ? ins(ls, l, mid, a) : ins(rs, mid + 1, r, a);
}

ll qmax(int k, int l, int r, int v) {
    if (l == r) return t[k](v);
    return max(t[k](v), mid >= v ? qmax(ls, l, mid, v) : qmax(rs, mid + 1, r, v));
}

| 下一页