李超线段树学习笔记

李超线段树学习笔记

李超线段树是一个维护一次函数的一种数据结构,通常来优化 dp。

跟线段树的原理是一样的,这里线段树的节点记的是一个线段的整体的最优线段,也就是一般的线段树的永久化标记。

这里讲一下如何区间修改。

  • 如果这个节点不被区间包含,按一般的线段树往下递归。

  • 如果更新的节点比原节点整体优,直接这个节点换掉。

  • 如果更新的节点比原节点整体劣,不做任何操作。

  • 如果这个节点小于一半比原节点优,在那一半递归下去。

  • 如果这个节点大于一半比原节点优,交换,同 4。

解释一下为什么要有 5 操作,因为若整体优就需要替换,而若整体劣,就直接跳出即可,不用时间复杂度。所以 5 这样的操作更好。

分析时间复杂度,分为两部分,传统线段树的区间修改,\(O(\log n)\) ,而后四步也类似一个区间修改,\(O(\log n)\),单次总时间复杂度 \(O(n\log n)\)

void change(int p,int l,int r,int L,int R,line x) {
	if(L<=l && r<=R){
		if(x.calc(l) > c[p].calc(l) && x.calc(r) > c[p].calc(r)){
			c[p]=x;
		}//覆盖
		else if(x.calc(l) > c[p].calc(l) || x.calc(r) > c[p].calc(r)   ) { //相交
			if(x.calc(mid)>c[p].calc(mid) )
				swap(x,c[p]);
			if(x.calc(l)>c[p].calc(l))
				change(ls,l,mid,L,R,x);
			else
				change(rs,mid+1,r,L,R,x);
		}
		return ;
	}
	else {
		if(L<=mid)change(ls,l,mid,L,R,x);
		if(R> mid)change(rs,mid+1,r,L,R,x);
	}
}

另外需要注意的是,单点修改是 \(O(\log n)\)

单点查询跟传统线段树一样,不做赘述。

区间查询需要再记一个数组,说明区间最优线段,其他都是一样的。

这里继续讲李超线段树合并。

好像没什么差别。。。

就是跟一般的线段树合并一样,最后多一个把区间最优线段插入在要合并的节点里。

int merge(int p,int q,int l,int r){
		if(!p || !q)return p|q;
		ls[p]=merge(ls[p],ls[q],l,mid);
		rs[p]=merge(rs[p],rs[q],mid+1,r);
		if(c[q].b < inf)change(p,l,r,c[q]);
		return p;
	}
posted @ 2025-08-01 21:45  hnczy  阅读(10)  评论(0)    收藏  举报