洛谷 - P4114 - Qtree1 - 重链剖分
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 - 重链剖分的更多相关文章
- 洛谷 P4114 Qtree1 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例: 输出样例: 说明 说明 思路 Change Query AC代码 总结 题面 题目链接 P4114 Qt ...
- 洛谷P4114 Qtree1(树链剖分+线段树)
传送门 LCT秒天秒地用什么树剖 这题可以算是树剖的比较裸的题目了 把每一条边的权值下放到他两边的点中深度较深的那个 然后直接用树剖+线段树带进去乱搞就可以了 //minamoto #include& ...
- 洛谷P4114 Qtree1
题目描述 给定一棵\(n\)个节点的树,有两个操作: \(CHANGE\) \(i\) \(t_i\) 把第\(i\)条边的边权变成\(t_i\) \(QUERY\) \(a\) \(b\) 输出从\ ...
- 洛谷 P4114 Qtree1
Qtree系列都跟树有着莫大的联系,这道题当然也不例外 我是题面 读完题,我们大概就知道了,这道题非常简单,可以说是模板题.树剖+线段树轻松解决 直接看代码吧 #include<algorith ...
- 树链剖分【洛谷P4114】 Qtree1
P4114 Qtree1 题目描述 给定一棵n个节点的树,有两个操作: CHANGE i ti 把第i条边的边权变成ti QUERY a b 输出从a到b的路径中最大的边权,当a=b的时候,输出0 码 ...
- 【算法学习】【洛谷】树链剖分 & P3384 【模板】树链剖分 P2146 软件包管理器
刚学的好玩算法,AC2题,非常开心. 其实很早就有教过,以前以为很难就没有学,现在发现其实很简单也很有用. 更重要的是我很好调试,两题都是几乎一遍过的. 介绍树链剖分前,先确保已经学会以下基本技巧: ...
- 洛谷P3384 树链剖分
如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x ...
- 洛谷.4114.Qtree1(树链剖分)
题目链接 模板题都错了这么多次.. //边权赋到点上 树剖模板 //注意LCA.链的顶端不能统计到答案! #include <cstdio> #include <cctype> ...
- 【树链剖分】洛谷P3379 树链剖分求LCA
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
随机推荐
- kettle中使用mysql的tinyint 类型到slqserver的tinyint类型
各个数据库之间的类型 定义还是有差别的 一下是我在工作中遇到的一个很奇葩的问题 mysql 中的 tinyint 类型 插入到sqlserver 的tinyint 类型 插入到 sqlserver的 ...
- tomcat的内存配置
WEB站点在跑安全测试时,跑一会儿就连接不上,考虑是否是tomcat内存溢出问题. Linux环境,修改Tomcat的内存配置: 修改bin/catalina.sh文件,在cygwin=false前面 ...
- 039:模版结构优化之include标签详解
引入模版: 有时候一些代码是在许多模版中都用到的.如果我们每次都重复的去拷贝代码那肯定不符合项目的规范.一般我们可以把这些重复性的代码抽取出来,就类似于Python中的函数一样,以后想要使用这些代码的 ...
- SQL Server2008收缩日志文件
查询状态语句: SELECT name,log_reuse_wait_desc FROM sys.databases where name='hrsystem'; 收缩日志文件: USE [maste ...
- oracle java for ubuntu apt-get
oracle java PPA: ppa:webupd8team/javathe key word use for search more infomation: webupd8team
- sql server 修改表字段
1.添加表说明 EXECUTE sp_addextendedproperty N'MS_Description','表说明',N'user',N'dbo',N'table',N'表名',NULL,NU ...
- idea使用"svn"到项目报错Error:Cannot run program "svn" (in directory "E:\XXXXXX"):CreateProcess error=2,
使用新项目工具idea界面上导入svn项目报错: Error:Cannot run program "svn" (in directory "D:\XXXXXX" ...
- 封装Qt的SQLite接口类
还没测试完善.. #ifndef SQLITE_H #define SQLITE_H #include <QSqlDatabase> #include <QSqlQuery> ...
- [ZJU 1004] Anagrams by Stack
ZOJ Problem Set - 1004 Anagrams by Stack Time Limit: 2 Seconds Memory Limit: 65536 KB How can a ...
- CF 480 B Long Jumps (map标记)
题目链接:http://codeforces.com/contest/480/problem/B 题目描述: Long Jumps Valery is a PE teacher at a ...