李超线段树学习笔记

用途

李超线段树的用法非常固定,一般就是让你求对于给出的一些线段或直线中,对于某个x最大的y是那个。

通常可以用于斜率优化。

而其的时间复杂度是 O(nlogn2)

思路

注:下文默认是线段,因为直线也只用改一下就行了。

我们建立一颗线段树,每个节点保存在当前区间,当x=mid时最大的线段的编号。

然后每次将两条线段进行比较,因为两条线段要么被另一条线段完全覆盖,要么只会覆盖左右区间中的一个(因为交点最多只有一个)。所以对于完全覆盖的,直接选择那一条直线,覆盖一半的,递归查找就行。

对于标记下传的话不太好直接下传,我们可以用标记永久化来做即可。注意因为是浮点数计算,注意要使用eps来判相等。

code

点击查看代码
#include<bits/stdc++.h> using namespace std; int n; const int N=100011; int p[N<<2]; double k[N],b[N]; double clac(int id,int x){ return 1.0*k[id]*x+1.0*b[id]; } int cnt=0; struct dot{ int xx,yy; }e1,e2; double eps=0.0000000001; void update(int rt,int l,int r,int u){ int mid=(l+r)>>1; if(!p[rt]){ p[rt]=u; // cout<<"u:"<<u<<endl; return ; } if(l==r){ int f=clac(u,mid);//bianhao int g=clac(p[rt],mid); if(f-g>eps)swap(p[rt],u); if(abs(f-g)<eps&&u<p[rt])p[rt]=u; return ; } else{ // cout<<"cnt:"<<u<<" "<<p[rt]<<" "<<l<<" "<<r<<endl; double f=clac(u,mid);//bianhao double g=clac(p[rt],mid); // cout<<"l,r.f,g:"<<l<<" "<<r<<" "<<f<<" "<<g<<endl; if(f-g>eps)swap(p[rt],u); // cout<<u<<" "<<p[rt]<<endl; if(clac(u,l)-clac(p[rt],l)>eps||(abs(clac(u,l)-clac(p[rt],l))<eps&&u<p[rt]))update(rt<<1,l,mid,u); if(clac(u,r)-clac(p[rt],r)>eps||(abs(clac(u,r)-clac(p[rt],r))<eps&&u<p[rt]))update(rt<<1|1,mid+1,r,u); } } void change(int rt,int l,int r,int L,int R){ if(L<=l&&r<=R){ // cout<<"l,r:"<<l<<" "<<r<<endl; update(rt,l,r,cnt); return ; } int mid=(l+r)>>1; if(L<=mid)change(rt<<1,l,mid,L,R); if(mid+1<=R)change(rt<<1|1,mid+1,r,L,R); return ; } int lastans,ans; double ansy; void ask(int rt,int l,int r,int d){ int mid=(l+r)>>1; double sum=clac(p[rt],d); if(sum-ansy>eps){ ansy=sum; ans=p[rt]; } if(abs(sum-ansy)<eps&&p[rt]<ans){ ans=p[rt]; ansy=sum; } if(l==r){ lastans=ans; cout<<lastans<<endl; ansy=0;ans=0; return ; } if(d<=mid)ask(rt<<1,l,mid,d); else ask(rt<<1|1,mid+1,r,d); return ; } #define mod 1000000000 int main(){ cin>>n; for(int i=1;i<=n;i++){ int op,t; cin>>op; if(op==0){ cin>>t; int x=(t+lastans-1)%39989+1; ask(1,1,39989,x); } else{ cin>>e1.xx>>e1.yy>>e2.xx>>e2.yy; e1.xx=(e1.xx+lastans-1)%39989+1; e2.xx=(e2.xx+lastans-1)%39989+1; e1.yy=(e1.yy+lastans-1)%mod+1; e2.yy=(e2.yy+lastans-1)%mod+1; if(e1.xx>e2.xx)swap(e1,e2); cnt++; // cout<<e1.xx<<" "<<e1.yy<<" "<<e2.xx<<" "<<e2.yy<<endl; if(e1.xx==e2.xx){ k[cnt]=0; b[cnt]=max(e1.yy,e2.yy); } else{ k[cnt]=(1.0*(e2.yy-e1.yy))/(1.0*(e2.xx-e1.xx)); b[cnt]=e1.yy-e1.xx*k[cnt]; } // cout<<k[cnt]<<" "<<b[cnt]<<endl; change(1,1,39989,e1.xx,e2.xx); } } }

__EOF__

本文作者shAdom
本文链接https://www.cnblogs.com/shadom/p/17611942.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   shAdomOvO  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示