题目


分析

就是把线段扔到了树上,注意区间查询要比较两个端点的函数值,

把区间赋值转换成两部分,从起点到LCA的区间是斜率为负数的线段,

从终点到LCA的区间是斜率为正数的线段。


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
typedef long long lll;
const int N = 100011;
struct node {
int y, w, next;
} e[N << 1];
int p[N << 2], Tot, dep[N], top[N], k = 1, tot, fat[N], nfd[N], dfn[N], son[N], big[N], n, m, as[N];
struct rec {
lll a, b;
} line[N << 1];
lll dis[N], w[N << 2];
inline signed iut() {
rr int ans = 0, f = 1;
rr char c = getchar();
while (!isdigit(c)) f = (c == '-') ? -f : f, c = getchar();
while (isdigit(c)) ans = (ans << 3) + (ans << 1) + (c ^ 48), c = getchar();
return ans * f;
}
inline void print(lll ans) {
if (ans < 0)
ans = -ans, putchar('-');
if (ans > 9)
print(ans / 10);
putchar(ans % 10 + 48);
}
inline lll min(lll a, lll b) { return a < b ? a : b; }
inline lll calc(int t, int x) { return line[t].a * dis[nfd[x]] + line[t].b; }
inline void build(int k, int l, int r) {
p[k] = 1, w[k] = line[1].b;
if (l == r)
return;
rr int mid = (l + r) >> 1;
build(k << 1, l, mid);
build(k << 1 | 1, mid + 1, r);
}
inline void update(int k, int l, int r, int x, int y, int z) {
rr int mid = (l + r) >> 1;
if (x <= l && r <= y) {
rr lll la = calc(p[k], l), lb = calc(z, l);
rr lll ra = calc(p[k], r), rb = calc(z, r), mb = min(lb, rb);
if (la <= lb && ra <= rb)
return;
if (la >= lb && ra >= rb) {
p[k] = z, w[k] = min(w[k], mb);
return;
}
rr double pos = 1.0 * (line[p[k]].b - line[z].b) / (line[z].a - line[p[k]].a);
if (la >= lb) {
if (pos <= dis[nfd[mid]])
update(k << 1, l, mid, x, y, z);
else
update(k << 1 | 1, mid + 1, r, x, y, p[k]), p[k] = z;
} else {
if (pos > dis[nfd[mid]])
update(k << 1 | 1, mid + 1, r, x, y, z);
else
update(k << 1, l, mid, x, y, p[k]), p[k] = z;
}
w[k] = min(min(w[k], mb), min(w[k << 1], w[k << 1 | 1]));
return;
}
if (x <= mid)
update(k << 1, l, mid, x, y, z);
if (mid < y)
update(k << 1 | 1, mid + 1, r, x, y, z);
w[k] = min(w[k], min(w[k << 1], w[k << 1 | 1]));
}
inline signed lca(int x, int y) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]])
x ^= y, y ^= x, x ^= y;
x = fat[top[x]];
}
if (dep[x] > dep[y])
x ^= y, y ^= x, x ^= y;
return x;
}
inline lll query(int k, int l, int r, int x, int y) {
if (l == x && r == y)
return w[k];
rr int mid = (l + r) >> 1;
rr lll lT = calc(p[k], x), rT = calc(p[k], y), mT = min(lT, rT);
if (y <= mid)
return min(mT, query(k << 1, l, mid, x, y));
else if (x > mid)
return min(mT, query(k << 1 | 1, mid + 1, r, x, y));
else
return min(mT, min(query(k << 1, l, mid, x, mid), query(k << 1 | 1, mid + 1, r, mid + 1, y)));
}
inline void Update(int x, int LCA, int z) {
for (; top[x] != top[LCA]; x = fat[top[x]]) update(1, 1, n, dfn[top[x]], dfn[x], z);
update(1, 1, n, dfn[LCA], dfn[x], z);
}
inline lll Query(int x, int y) {
rr lll ans = line[1].b;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]])
x ^= y, y ^= x, x ^= y;
ans = min(ans, query(1, 1, n, dfn[top[x]], dfn[x]));
x = fat[top[x]];
}
if (dep[x] > dep[y])
x ^= y, y ^= x, x ^= y;
return ans = min(ans, query(1, 1, n, dfn[x], dfn[y]));
}
inline void dfs1(int x, int fa) {
dep[x] = dep[fa] + 1, fat[x] = fa, son[x] = 1;
for (rr int i = as[x], mson = -1; i; i = e[i].next)
if (e[i].y != fa) {
dis[e[i].y] = dis[x] + e[i].w, dfs1(e[i].y, x), son[x] += son[e[i].y];
if (son[e[i].y] > mson)
big[x] = e[i].y, mson = son[e[i].y];
}
}
inline void dfs2(int x, int linp) {
dfn[x] = ++tot, nfd[tot] = x, top[x] = linp;
if (!big[x])
return;
dfs2(big[x], linp);
for (rr int i = as[x]; i; i = e[i].next)
if (e[i].y != fat[x] && e[i].y != big[x])
dfs2(e[i].y, e[i].y);
}
signed main() {
n = iut();
m = iut();
for (rr int i = 1; i < n; ++i) {
rr int x = iut(), y = iut(), w = iut();
e[++k] = (node){ y, w, as[x] }, as[x] = k;
e[++k] = (node){ x, w, as[y] }, as[y] = k;
}
line[Tot = 1] = (rec){ 0, 123456789123456789ll };
dfs1(1, 0), dfs2(1, 1), build(1, 1, n);
for (rr int i = 1; i <= m; ++i)
if (iut() & 1) {
rr int x = iut(), y = iut(), A = iut(), B = iut(), LCA = lca(x, y);
line[++Tot] = (rec){ -A, dis[x] * A + B }, Update(x, LCA, Tot);
line[++Tot] = (rec){ A, (dis[x] - dis[LCA] * 2) * A + B }, Update(y, LCA, Tot);
} else
print(Query(iut(), iut())), putchar(10);
return 0;
}

#李超线段树,树链剖分#洛谷 4069 [SDOI2016]游戏的更多相关文章

  1. 洛谷P4069 [SDOI2016]游戏(李超线段树)

    题意 题目链接 Sol 这题细节好多啊qwq..稍不留神写出一个小bug就要调1h+.. 思路就不多说了,把询问区间拆成两段就是李超线段树板子题了. 关于dis的问题可以直接维护. // luogu- ...

  2. 洛谷P4069 [SDOI2016]游戏(李超线段树)

    题面 传送门 题解 如果我们把路径拆成两段,那么这个路径加可以看成是一个一次函数 具体来说,设\(dis_u\)表示节点\(u\)到根节点的距离,那么\((x,lca)\)这条路径上每个节点的权值就会 ...

  3. AC日记——【模板】树链剖分 洛谷 P3384

    题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...

  4. 洛谷 P2197 nim游戏

    洛谷 P2197 nim游戏 题目描述 甲,乙两个人玩Nim取石子游戏. nim游戏的规则是这样的:地上有n堆石子(每堆石子数量小于10000),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取 ...

  5. 洛谷 P1965 转圈游戏

    洛谷 P1965 转圈游戏 传送门 思路 每一轮第 0 号位置上的小伙伴顺时针走到第 m 号位置,第 1 号位置小伙伴走到第 m+1 号位置,--,依此类推,第n − m号位置上的小伙伴走到第 0 号 ...

  6. 洛谷 P4072 [SDOI2016]征途 斜率优化DP

    洛谷 P4072 [SDOI2016]征途 斜率优化DP 题目描述 \(Pine\) 开始了从 \(S\) 地到 \(T\) 地的征途. 从\(S\)地到\(T\)地的路可以划分成 \(n\) 段,相 ...

  7. 李超线段树(segment[HEOI2013]-洛谷T4097)

    (neng了好久好久才糊弄懂得知识点...) 一.李超线段树 在线动态维护一个二维平面直角坐标系, 支持插入一条线段, 询问与直线x = x0相交的所有线段中,交点y的最大/小值 (若有多条线段符合条 ...

  8. 树剖模板(洛谷P3384 【模板】树链剖分)(树链剖分,树状数组,树的dfn序)

    洛谷题目传送门 仍然是一个板子. 不过蒟蒻去学了一下BIT维护区间修改区间求和,常数果真十分优秀 设数列为\(a_i\),差分数组\(d_ i=a_ i-a_ {i-1}\),前缀和\(s_i=\su ...

  9. 线段树分治初步学习&洛谷P5227[AHOI2013]连通图

    线段树分治 其实思想说起来是比较简单的,我们把这个题里的所有操作(比如连边删边查询balabala)全部拍到一棵线段树上,然后对着整棵树dfs一下求解答案,顺便把操作做一下,回溯的时候撤销一下即可.虽 ...

  10. 线段树&数链剖分

    傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...

随机推荐

  1. Postman文件数据导入导出

    https://zhuanlan.zhihu.com/p/535757471?utm_id=0

  2. Qt实用技巧:QCustomPlot做北斗GPS显示绝对位置运动轨迹和相对位置运动轨迹图的时,使图按照输入点顺序连曲线

    需求   使用QCustomPlot绘制多个目标的北斗运行轨迹图,包括累计绝对位置图和记录时刻的相对位置图.  当前绘制存在问题:    交付客户前,公司内部自测流程发现的问题.  实际预期效果为:  ...

  3. VUE 腾讯云 web端上传视频SDK 上传进度无法显示

    上传视频官方文档:https://cloud.tencent.com/document/product/266/9239 错误信息 在本地调试可以显示视频上传进度,也可以打印到浏览器控制台.但是,发布 ...

  4. 【Azure 应用服务】Azure App Service能否使用Storage Account File Share

    问题描述 Azure App Service能否使用Storage Account File Share? 问题回答 如果部署的App Service为Linux环境,可以直接使用Mount stor ...

  5. 文心一言 VS 讯飞星火 VS chatgpt (210)-- 算法导论16.1 1题

    一.根据递归式(16.2)为活动选择问题设计一个动态规划算法.算法应该按前文定义计算最大兼容活动集的大小 c[i,j]并生成最大集本身.假定输入的活动已按公式(16.1)排好序.比较你的算法和GREE ...

  6. OPPO 后端面试凉经(附详细参考答案)

    这篇文章的问题来源于一个读者之前分享的 OPPO 后端凉经,我对比较典型的一些问题进行了分类并给出了详细的参考答案.希望能对正在参加面试的朋友们能够有点帮助! Java String 为什么是不可变的 ...

  7. 基于python的json和cvs格式转换

    一 概念 1 json: JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 易于人阅读和编写.同时也易于机器解析和生成. 它基于JavaScript Pr ...

  8. C++小细节

    cin不仅遇到EOF会返回无效状态(通常用来终止循环),遇到无效输入的时候也会返回无效状态,比如向整型变量输入字符. char类型的大小和机器有关,最小8位,大多数机器字节(byte)是8位,byte ...

  9. AOSP编译成功后关闭终端emulator命令找不到

    当我们编译好AOSP系统源码后,可以通过emulator命令打开模拟器,但是当我们关闭终端后,在次打开终端输入emulator命令,提示未找到命令: 此时我们需要重新执行下面语句 source bui ...

  10. 不要升级!不要升级!MacOS 14.4 引发Java 应用崩溃

    如果最近您收到了MacOS 14.4的升级提醒,那么建议你暂时先不要升级! 在x上,Java开发领域的一些大v们,也发现了这个问题,并提醒大家不要升级. 根据Java官方发布的文章了解到,该问题主要是 ...