李超线段树
李超线段树
用来维护线段(一次函数)信息。
值域线段树:#
对于值域线段树维护
添加操作:#
新边
1.将边拆为最多
2.如果
3.如果有交点,则递归到有交点的那一侧。(
对于递归,就是在该区间去最优边,再将另一条边传到子节点。
查询操作:#
记录从根到叶子节点这一条链上的最优边。
struct line{dou k, b;}L[N];
dou clac(int u, dou x){return L[u].k * x + L[u].b;}
void add(dou x, dou y, dou X, dou Y){
if(x == X) L[++cnt] = {0, max(y, Y)};
else L[++cnt].k = (Y - y) / (X - x), L[cnt].b = Y - L[cnt].k * X;
}
int cmp(dou x, dou y){
if(x - y > eps) return 1;
if(y - x > eps) return -1;
return 0;
}
struct L_S_T{
#define ld rt * 2
#define rd rt * 2 + 1
#define mid (cl + cr >> 1)
int s[M << 2];
void cg(int rt, int cl, int cr, int u){
int &v = s[rt];
int bmid = cmp(clac(u, mid), clac(v, mid));
if(bmid == 1 || (!bmid && u < v)) swap(u, v);
int bl = cmp(clac(u, cl), clac(v, cl)), br = cmp(clac(u, cr), clac(v, cr));
if(bl == 1 || (!bl && u < v)) cg(ld, cl, mid, u);
if(br == 1 || (!br && u < v)) cg(rd, mid + 1, cr, u);
}
void modify(int rt, int cl, int cr, int l, int r, int u){
if(l <= cl && r >= cr){
cg(rt, cl, cr, u);
return ;
}
if(l <= mid) modify(ld, cl, mid, l, r, u);
if(r > mid) modify(rd, mid + 1, cr, l, r, u);
}
int check(int u, int v, int x){
if(cmp(clac(u, x), clac(v, x)) == 1) return u;
if(cmp(clac(u, x), clac(v, x)) == 0) return min(u, v);
return v;
}
int query(int rt, int cl, int cr, int k){
int res = s[rt];
if(cl == cr) return res;
if(k <= mid) res = check(res, query(ld, cl, mid, k), k);
else res = check(res, query(rd, mid + 1, cr, k), k);
return res;
}
}S;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具