https://www.luogu.org/problem/P4114

维护边权的话,用深度大的点表示这条边(可以遍历一边边询问两端深度,这样不需要修改dfs1,也可以在dfs1的时候向下走的同时把边权拷贝进深度大的点。),然后在链上问的时候,最后一次问的左端点要+1(小心左右端点原本重合)。

要注意每个点x实际上在线段树上的位置是tid[x],不要改错了。线段树build的时候初始化的不是a[x]而是a[rnk[x]],也就是x号线段树位置对应的dfn序,也就是节点本身(rnk和tid互为逆运算)。

#include<bits/stdc++.h>
#define lc (o<<1)
#define rc (o<<1|1)
typedef long long ll;
using namespace std; const ll INF = 1e18; const int MAXN = 100000 + 5;
int dep[MAXN], siz[MAXN], son[MAXN], fa[MAXN], top[MAXN], tid[MAXN], rnk[MAXN], cnt; int n, m; int head[MAXN], etop;
struct Edge {
int v, w, next;
} e[MAXN * 2]; inline void init(int n) {
etop = 0;
memset(head, -1, sizeof(head[0]) * (n + 1));
} inline void addedge(int u, int v, int w) {
e[++etop].v = v;
e[etop].w = w;
e[etop].next = head[u];
head[u] = etop;
e[++etop].v = u;
e[etop].w = w;
e[etop].next = head[v];
head[v] = etop;
} int a[MAXN]; struct SegmentTree {
int ma[MAXN * 4]; void build(int o, int l, int r) {
if(l == r) {
ma[o] = a[rnk[l]];
} else {
int m = (l + r) >> 1;
build(lc, l, m);
build(rc, m + 1, r);
pushup(o);
}
} void pushup(int o) {
ma[o] = max(ma[lc], ma[rc]);
} void update(int o, int l, int r, int x, int v) {
if(l == r) {
ma[o] = v;
} else {
int m = (l + r) >> 1;
if(x <= m)
update(lc, l, m, x, v);
if(x >= m + 1)
update(rc, m + 1, r, x, v);
pushup(o);
}
} ll querymax(int o, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr) {
return ma[o];
} else {
int m = (l + r) >> 1;
ll res = -INF;
if(ql <= m)
res = max(res, querymax(lc, l, m, ql, qr));
if(qr >= m + 1)
res = max(res, querymax(rc, m + 1, r, ql, qr));
return res;
}
}
} st; void init1() {
dep[1] = 1;
} void dfs1(int u, int t) {
siz[u] = 1, son[u] = -1, fa[u] = t;
for(int i = head[u]; i != -1; i = e[i].next) {
int v = e[i].v;
if(v == t)
continue;
dep[v] = dep[u] + 1;
a[v]=e[i].w;
dfs1(v, u);
siz[u] += siz[v];
if(son[u] == -1 || siz[v] > siz[son[u]])
son[u] = v;
}
} void init2() {
cnt = 0;
} void dfs2(int u, int t) {
top[u] = t;
tid[u] = ++cnt;
rnk[cnt] = u;
if(son[u] == -1)
return;
dfs2(son[u], t);
for(int i = head[u]; i != -1; i = e[i].next) {
int v = e[i].v;
if(v == fa[u] || v == son[u])
continue;
dfs2(v, v);
}
} ll querymax1(int u, int v) {
if(u == v)
return 0;
ll ret = -INF;
for(int tu = top[u], tv = top[v]; tu != tv; u = fa[tu], tu = top[u]) {
if(dep[tu] < dep[tv])
swap(u, v), swap(tu, tv);
ret = max(ret, st.querymax(1, 1, n, tid[tu], tid[u]));
}
if(tid[u] == tid[v])
return ret;
if(dep[u] > dep[v])
swap(u, v);
ret = max(ret, st.querymax(1, 1, n, tid[u] + 1, tid[v]));
return ret;
} void change() {
int i, val;
scanf("%d%d", &i, &val);
int u = e[2*i-1].v, v = e[2*i].v;
int x = u;
if(dep[v] > dep[u])
x = v;
st.update(1, 1, n, tid[x], val);
} void query() {
int u, v;
scanf("%d%d", &u, &v);
ll res = querymax1(u, v);
printf("%lld\n", res);
} int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
scanf("%d", &n);
init(n);
for(int i = 1, u, v, w; i <= n - 1; ++i) {
scanf("%d%d%d", &u, &v, &w);
addedge(u, v, w);
}
init1(),dfs1(1, -1);
init2(),dfs2(1, 1);
st.build(1, 1, n);
char op[20];
while(~scanf("%s", op)) {
switch(op[0]) {
case 'C':
change();
break;
case 'Q':
query();
break;
case 'D':
return 0;
}
}
return 0;
}

洛谷 - P4114 - Qtree1 - 重链剖分的更多相关文章

  1. 洛谷 P4114 Qtree1 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例: 输出样例: 说明 说明 思路 Change Query AC代码 总结 题面 题目链接 P4114 Qt ...

  2. 洛谷P4114 Qtree1(树链剖分+线段树)

    传送门 LCT秒天秒地用什么树剖 这题可以算是树剖的比较裸的题目了 把每一条边的权值下放到他两边的点中深度较深的那个 然后直接用树剖+线段树带进去乱搞就可以了 //minamoto #include& ...

  3. 洛谷P4114 Qtree1

    题目描述 给定一棵\(n\)个节点的树,有两个操作: \(CHANGE\) \(i\) \(t_i\) 把第\(i\)条边的边权变成\(t_i\) \(QUERY\) \(a\) \(b\) 输出从\ ...

  4. 洛谷 P4114 Qtree1

    Qtree系列都跟树有着莫大的联系,这道题当然也不例外 我是题面 读完题,我们大概就知道了,这道题非常简单,可以说是模板题.树剖+线段树轻松解决 直接看代码吧 #include<algorith ...

  5. 树链剖分【洛谷P4114】 Qtree1

    P4114 Qtree1 题目描述 给定一棵n个节点的树,有两个操作: CHANGE i ti 把第i条边的边权变成ti QUERY a b 输出从a到b的路径中最大的边权,当a=b的时候,输出0 码 ...

  6. 【算法学习】【洛谷】树链剖分 & P3384 【模板】树链剖分 P2146 软件包管理器

    刚学的好玩算法,AC2题,非常开心. 其实很早就有教过,以前以为很难就没有学,现在发现其实很简单也很有用. 更重要的是我很好调试,两题都是几乎一遍过的. 介绍树链剖分前,先确保已经学会以下基本技巧: ...

  7. 洛谷P3384 树链剖分

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

  8. 洛谷.4114.Qtree1(树链剖分)

    题目链接 模板题都错了这么多次.. //边权赋到点上 树剖模板 //注意LCA.链的顶端不能统计到答案! #include <cstdio> #include <cctype> ...

  9. 【树链剖分】洛谷P3379 树链剖分求LCA

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

随机推荐

  1. namenode和datanode的高可用性和故障处理

    一.Hadoop单点故障问题如何解决 Hadoop 1.0内核主要由两个分支组成:MapReduce和HDFS,众所周知,这两个系统的设计缺陷是单点故障,即MR的JobTracker和HDFS的Nam ...

  2. ubuntu重装--备份/配置

    https://github.com/wenlin-gk/document/blob/master/ubuntu%E5%A4%87%E4%BB%BD%2B%E9%85%8D%E7%BD%AE.txt

  3. 049:ORM常用Field详解(1)

    常用字段: 在 Django 中,定义了一些 Field 来与数据库表中的字段类型来进行映射.以下将介绍那些常用的字段类型. AutoField: 映射到数据库中是 int 类型,可以有自动增长的特性 ...

  4. zabbix监控A主机到B主机的网络质量

    采用zabbix自带的icmp ping即可进行监控: 1.安装fping 2.将fping安装后链接到/usr/sbin/fping下,设置组为zabbix; 3.增加监控项:icmpping[ip ...

  5. 无线网络中的MIMO与OFDM技术原理分析

    无线网络中的MIMO与OFDM技术原理分析CNET中国·ZOL 07年08月14日 [原创] 作者: 中关村在线 张伟 从最早的红外线技术到目前被寄予重望的WIFI,无线技术的进步推动我们的网络一步步 ...

  6. ECharts插件介绍(图表库)

    ECharts是一个非常好用的插件,用于进行 树状图,折线图,饼图,地图等等,系列视图的绘制.(详情看官网) 了解: AMD:模块化开发方式: 引入文件后:console.log(echarts) / ...

  7. leetcode-mid-Linked list- 230 Kth Smallest Element in a BST

    mycode  81.40% # Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x ...

  8. leetcode-mid-Linked list- 105. Construct Binary Tree from Preorder and Inorder Traversal

    mycode   43.86% # Definition for a binary tree node. # class TreeNode(object): # def __init__(self, ...

  9. principal components analysis 主成份分析

    w http://deeplearning.stanford.edu/wiki/index.php/主成份分析 主成分分析(PCA)及其在R里的实现 - jicf的日志 - 网易博客  http:// ...

  10. CentOS7 日常操作 2

    常用命令 文件与目录操作 命令 解析 cd /home 进入 ‘/home’ 目录 cd .. 返回上一级目录 cd ../.. 返回上两级目录 cd - 返回上次所在目录 cp file1 file ...