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

浅谈李超线段树

时间:2024-10-11 21:21:54浏览次数:1  
标签:浅谈 更优 int 线段 mid 李超 区间 dt

众所周知,\(Li\ Chao\ Tree=LCT=Link\ Cut\ Tree\)。


在我们的日常学习生活中,经常会遇到以下问题:

维护一种数据结构,要求:

  1. 添加一条线段
  2. 求解 \(x=k\) 与所有线段交点中,\(y\) 最大的一个。

众所周知,线段会影响一个区间的答案。区间取 \(max+\) 单点最大值,想到线段树。

但是该怎么修改哩?

我们设 \(dt_{l,r}\) 表示完全覆盖 \([l,r]\) 的所有线段中,与 \(x=mid\) 的交点 \(y\) 值最大的那条线段的编号。

那么发现如下性质:

  1. 假如新线段与老线段相比,\(x=l\) 和 \(x=r\) 时都更优,那么新线段在整个区间中都完爆老线段。
  2. 假如新线段与老线段相比,\(x=l\) 和 \(x=r\) 时都更劣,那么老线段在整个区间中都完爆新线段。

这两种情况直接改变 \(dt_{l,r}\) 的值就可以了,假如用标记永久化就可以 \(return\) 掉了。

发现假如不符合上述性质,且 \(x=mid\) 时新线段优于老线段,那么可以理解为原来是新线段,加入老线段,直接交换即可。

那么我们现在考虑的问题就是:新线段有可能在哪一段比原先更优。

发现假如 \(x=l\) 时新线段更优,那么只有在 \([l,mid]\) 里,新线段才可能更优,反之亦然。这个手模很好理解。

那么用线段树实现这个过程就好了。

分析时间复杂度:

由于对 \(dt\) 的定义,导致我们必须找到所有被新线段包含区间(数量级为 \(O(\log n)\)),再进行类似单点修改的操作,所以时间复杂度轻轻松松 \(O(n\log^2n)\)。

特别的,当插入的是直线时,第一步的数量级变为 \(O(1)\),所以时间复杂度为 \(O(n\log n)\)。

#include<bits/stdc++.h>
#define int long long
#define $ inline
using namespace std;
const int N=2e5+5,q=39989,p=1e9;
const double eps=1e-8;
int n,la=-1,id;
double k[N],b[N];
int dcmp(double x){
	return fabs(x)<=eps?0:x<0?-1:1;
}double f(int x,int y){
	return k[x]*y+b[x];
}int ju(int x,int y,int p){
	double fx=f(x,p),fy=f(y,p);
	return dcmp(fx-fy)?fx<fy:x>y;
}struct Lichao{
	int dt[N];
	$ void upd(int x,int l,int r,int L,int R,int v){
		if(L<=l&&r<=R){
			if(ju(v,dt[x],l)&&ju(v,dt[x],r)) return;
			if(ju(dt[x],v,l)&&ju(dt[x],v,r)) return dt[x]=v,void();
			int mid=(l+r)>>1;
			if(ju(dt[x],v,mid)) swap(dt[x],v);
			if(ju(dt[x],v,l)) upd(x<<1,l,mid,L,R,v);
			else upd(x<<1|1,mid+1,r,L,R,v);
			return;
		}int mid=(l+r)>>1;
		if(L<=mid) upd(x<<1,l,mid,L,R,v);
		if(R>mid) upd(x<<1|1,mid+1,r,L,R,v);
	}$ int que(int x,int l,int r,int v){
		if(l==r) return dt[x];
		int mid=(l+r)>>1,re=0;
		if(v<=mid) re=que(x<<1,l,mid,v);
		else re=que(x<<1|1,mid+1,r,v);
		return (!ju(re,dt[x],v))?re:dt[x]; 
	}
}lcst;//Link Cut Tree=Li Chao Tree?
void t(int &x,int qp){
	x=(x+la+qp)%qp+1;
}void solve0(){
	int xa,ya,xb,yb;
	cin>>xa>>ya>>xb>>yb;
	t(xa,q),t(xb,q),t(ya,p),t(yb,p);
	if(xb<xa) swap(xa,xb),swap(ya,yb);
	if(xa==xb) k[++id]=0,b[id]=max(ya,yb);
	else k[++id]=1.0*(yb-ya)/(xb-xa),b[id]=yb-k[id]*xb;
	lcst.upd(1,1,4e4,xa,xb,id);
}void solve1(){
	int k;cin>>k,t(k,q);
	la=lcst.que(1,1,4e4,k);
	cout<<la<<"\n",la--;
}signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		int opt;cin>>opt;
		if(!opt) solve1();
		else solve0();
	}return 0;
}//基本逻辑:寻找区间中点最优解

标签:浅谈,更优,int,线段,mid,李超,区间,dt
From: https://www.cnblogs.com/chang-an-22-lyh/p/18459371/tj-lichaotree

相关文章

  • 浅谈一类动态开点线段树优化 - DEST树
    前言线段树,是一种优秀的数据结构,其应用极为广泛。其中,动态开点值域线段树,配合上线段树合并,甚至能替代或超越平衡树。但是,这种线段树的树高与值域相关,很容易产生四五倍常数。无论考虑时间或空间复杂度,这样的树都不算优。那么,我们是否能想办法优化它呢?优化思想正如上文所述,普通线......
  • 可持久化线段树
    可持久化线段树P3919【模板】可持久化线段树1(可持久化数组)维护一个长度为\(N\)的数组,支持如下几种操作在某个历史版本上修改某一个位置上的值访问某个历史版本上的某一位置的值此外,每进行一次操作(对于操作2,即为生成一个完全一样的版本,不作任何改动),就会生成一个新......
  • 浅谈云原生--微服务、CICD、Serverless、服务网格
    往期推荐 浅学React和JSX-CSDN博客一文搞懂大数据流式计算引擎Flink【万字详解,史上最全】-CSDN博客一文入门大数据准流式计算引擎Spark【万字详解,全网最新】_大数据spark-CSDN博客目录1.云原生概念和特点2.常见云模式3.云对外提供服务的架构模式3.1IaaS(Infrast......
  • 李超线段树
    1问题李超线段树是线段树的一种变种,主要用于维护二维平面上的直线信息以及查询操作。它的应用范围很广,只要式子的形式能转化为一次函数就可以考虑使用李超线段树进行求解/优化。具体的,李超线段树支持下面两种操作:动态在平面中插入一条线段/直线。在平面上询问与一条直线......
  • Mysql锁机制浅谈一
    mysql是如何加锁的?加锁默认是加临键锁,有特殊情况会优化为其他锁索引上的等值查询:唯一索引,给不存在的记录加锁时,优化为间隙锁普通索引,向右遍历至最后一个不满足查询条件的值时吗退化为间隙锁索引上的范围查询:唯一索引:访问到不满足条件的第一个值为止主键索引ps:如果是......
  • 浅谈SG函数
    文章目录写在前面公平游戏写在前面听说CSDN给米就来了,不过作为一个品质优良的程序员来说,无私奉献是我应该做的,所以博主写的文章基本上不花钱,都是为了以后某天忘记了,自己能看懂才写的。so,我会写的很啰嗦,直到保证忘记的我能够看懂。对于读者嘛,能看就看吧,我就不管了。......
  • 李超线段树
    最经典应用就是维护一个二维平面直角坐标系,支持动态插入线段(理解为有值域的一次函数\(y=kx+b\)),询问已插入线段与直线\(x=x_0\)交点的纵坐标最值。即当\(x=x_0\),求\(max\)或\(min\){\(k_ix+b_i\)}对于普通求法的\(O(n)\)遍历,如何优化时间复杂度呢?其实就是找一种方......
  • B. 线段取交
    题目下载链接算法可以发现是求逆序对时间复杂度限制在\(O(n\logn)\)树状数组记录每一个值的多少转化为求前缀和#include<iostream>#include<cstdio>#include<algorithm>usingnamespacestd;inttree[500010],ranks[500010],n;longlongans;structpoint{......
  • 浅谈 $prufer$ 序列
    \(purfer\)序列,是为了证明\(cayley\)定理。具体来说,是将一个树映射到一个数组上,在数组上可以使得很多东西更加清晰的展示。构造\(prufer\)序列\(prufer\)是将一个大小为\(n\)的树映射到长度\(n-2\)的序列上。从一个无根树开始,我们将树入度为\(1\)的点找出来,及叶子......
  • 浅谈IT行业的未来发展趋势
    浅谈IT行业的未来发展趋势随着科技的不断进步,IT行业的发展进入了一个崭新的阶段。今天,我们就来浅谈一下IT行业的未来发展趋势,探讨那些可能会改变我们生活的技术。1.人工智能与自动化人工智能(AI)和自动化技术已经在各个领域崭露头角。未来,随着AI算法的进一步优化和硬件性......