peng1984729又是摸鱼的一天!!

李超线段树

Peng·2024-07-15 21:51·9 次阅读

李超线段树

李超线段树

用来维护线段(一次函数)信息。

值域线段树:#

对于值域线段树维护x轴 上的区间[l,r],维护s,表示在x=mid可能取最大值的线段(不一定就是最大)。

添加操作:#

新边u,旧边v

1.将边拆为最多log个在线段树上的线段。

2.如果uv存在完全覆盖关系,就直接去最优边。

3.如果有交点,则递归到有交点的那一侧。(log层)

对于递归,就是在该区间去最优边,再将另一条边传到子节点。

查询操作:#

记录从根到叶子节点这一条链上的最优边。

Copy
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;
posted @   peng1984729  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示
目录