李超线段树
考试的时候考的板子,但是我不会。
P4097 【模板】李超线段树 / [HEOI2013] Segment
修改:插入一条线段。查询:有某条竖直直线,与某些线段有交点,求交点最高的线段编号。相同高度输出编号小的。复杂度 \(n\log^2 n\)。
考虑线段树维护。线段树上的每个节点存下当前节点所对应的区间中点的最优线段编号。
可以发现大部分时候我们都不能像普通线段树的区间修改一样去把区间拆成 \(\log n\) 个区间来打标记。因为区间中点的最优线段这个性质没有结合律,大区间不能完全代表小区间的并。
但是由于没有删除只有插入,同时是单点查询(其实区间查询应该也能做),复杂度的阈值又很高,因此标记永久化以后可以拆成 \(\log^2 n\) 个节点来操作。
具体而言,我们还是先把区间拆成 \(\log n\) 段,然后对于拆开的每一段,我们都先更新当前区间中点的最优值。
但是可能出现被当前区间中点淘汰的线段在当前区间某一端更优的情况。我们单侧递归下去暴力修改复杂度就是对的。
code
需要注意的是,某些题目的横坐标的值域会很大,需要离散化后像扫描线那样去操作。
只是这道题出题人比较良心,什么都不用写。
#include<bits/stdc++.h>
using namespace std;
#define ld double
const int N=5e5+7;
int n,m,lst=0,cnt,tr[N];ld k[N],b[N];
#define ls (u<<1)
#define rs (u<<1|1)
bool eq(ld a,ld b){ld tmp=1e-10;if(a-b<=tmp&&b-a<=tmp) return true;else return false;}
ld get(int u,int x){return (ld)k[u]*x+b[u];}
bool cmp(int u,int v,int x){
ld a=get(u,x),b=get(v,x);
return a>b||(eq(a,b)&&u<v);
}
void update(int u,int l,int r,int t){
int mid=(l+r)>>1;
if(cmp(t,tr[u],mid)) swap(tr[u],t);
if(l==r) return;
if(cmp(t,tr[u],l)) update(ls,l,mid,t);
if(cmp(t,tr[u],r)) update(rs,mid+1,r,t);
}
void modify(int u,int l,int r,int ql,int qr,int t){
if(ql<=l&&r<=qr){update(u,l,r,t);return;}
int mid=(l+r)>>1;
if(ql<=mid) modify(ls,l,mid,ql,qr,t);
if(qr>mid) modify(rs,mid+1,r,ql,qr,t);
}
int query(int u,int l,int r,int x){
if(l==r) return tr[u];
int mid=(l+r)>>1,res=tr[u],tmp;
if(x<=mid) tmp=query(ls,l,mid,x);else tmp=query(rs,mid+1,r,x);
if(cmp(tmp,res,x))res=tmp;return res;
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n;
while(n--){
int op;ld lx,ly,rx,ry;cin>>op;
if(op==0){
int k;cin>>k;k=(k+lst-1+39989)%39989+1;
lst=query(1,1,39989,k);cout<<lst<<'\n';
}
else{
cin>>lx>>ly>>rx>>ry;lx=((int)(lx+lst-1+39989)%39989)+1;rx=((int)(rx+lst-1+39989)%39989)+1;ly=((int)(ly+lst-1+1000000000)%(1000000000))+1;ry=((int)(ry+lst-1+1000000000)%(1000000000))+1;
if(lx>rx) swap(lx,rx),swap(ly,ry);
if(lx==rx) {k[++cnt]=0;b[cnt]=max(ly,ry);}else {k[++cnt]=(ld)(ry-ly)/(rx-lx);b[cnt]=ly-k[cnt]*lx;}
modify(1,1,39989,lx,rx,cnt);
}
}
return 0;
}
李超线段树的应用主要还是DP中的斜率优化。直接应用在数据结构中的不多。斜率优化

浙公网安备 33010602011771号