【学习笔记】李超线段树
李超线段树
题目描述
要求在平面直角坐标系下维护两个操作:
- 在平面上加入一条线段。记第 条被插入的线段的标号为 。
- 给定一个数 ,询问与直线 相交的线段中,交点纵坐标最大的线段的编号。
线段端点横坐标范围40000,考虑用线段树维护,线段树的每一个点上维护一条线段。
线段树上一点的 即为对应的线段。
当然因为线段左右端点有范围,所以要先找到线段树对应的区间。
而后讨论当前线段和当前点对应的线段关系。
具体看代码。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
inline int rd(){
int f=1,j=0;
char w=getchar();
while(w>'9'||w<'0'){
if(w=='-')f=-1;
w=getchar();
}
while(w>='0'&&w<='9'){
j=(j<<3)+(j<<1)+w-'0';
w=getchar();
}
return f*j;
}
const int N=100001,M=40000,mod=39989,mod2=1000000000;
const double E=0.0000001;
struct Line{
double k,b;
inline double operator [](int x){return k*x+b;}
}lin[N];
struct node{
int l,r,t;
}tr[M*20];
int n,tail,lastans,siz,ans;
inline void addline(int t,int xa,int ya,int xb,int yb){
if(xa==xb)lin[t].k=0,lin[t].b=max(ya,yb);
else lin[t].k=(double)(yb-ya)/(xb-xa),lin[t].b=(double)ya-lin[t].k*xa;
return ;
}
void add(int u,int l,int r,int L,int R,int t){
int mid=(l+r)/2;
if(L<=l&&r<=R){
if(!tr[u].t||(lin[tr[u].t][l]<lin[t][l]&&lin[tr[u].t][r]<lin[t][r])){
tr[u].t=t;
return ;
}
if(l==r||(lin[tr[u].t][l]>lin[t][l]&&lin[tr[u].t][r]>lin[t][r]))return ;
if(lin[tr[u].t][mid]<lin[t][mid])swap(tr[u].t,t);
if(lin[tr[u].t][l]<=lin[t][l])add(u*2,l,mid,L,R,t);
else if(lin[tr[u].t][r]<=lin[t][r])add(u*2+1,mid+1,r,L,R,t);
return ;
}
else{
if(L<=mid)add(u*2,l,mid,L,R,t);
if(mid<R)add(u*2+1,mid+1,r,L,R,t);
}
return ;
}
void getans(int u,int l,int r,int aim){
if(tr[u].t&&(lin[tr[u].t][aim]>lin[ans][aim]||(tr[u].t<ans&&lin[tr[u].t][aim]>lin[ans][aim]-E&&lin[tr[u].t][aim]<lin[ans][aim]+E)))ans=tr[u].t;
if(l==r)return ;
int mid=(l+r)/2;
if(aim<=mid)getans(u*2,l,mid,aim);
else getans(u*2+1,mid+1,r,aim);
return ;
}
signed main(){
n=rd();
lin[0].k=lin[0].b=-1;
while(n--){
int op=rd();
if(op==1){
int xa=(rd()+lastans-1)%mod+1,ya=(rd()+lastans-1)%mod2+1,xb=(rd()+lastans-1)%mod+1,yb=(rd()+lastans-1)%mod2+1;
if(xa>xb)swap(xa,xb),swap(ya,yb);
addline(++siz,xa,ya,xb,yb);
add(1,1,mod,xa,xb,siz);
}
else{
ans=0;
getans(1,1,mod,(rd()+lastans-1)%mod+1);
printf("%d\n",lastans=ans);
}
}
return 0;
}
我才不会说因为交点精度问题被卡了好几次呢
标记永久化
看到luogu上好多题解都说什么标记永久化之类的,一直不明白是什么东西。
如果按照自己的理解来说,这大概是一种类似与树上子树整体修改(改子树根节点,求单点权值即求点到根的路径和)
类似的,标记永久化即标记打到包含其所有情况的点,状态不下传,求单点状态就从当前点跑到根。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】