[SPOJ375]QTREE - Query on a tree【树链剖分】
题目描述
给你一棵树,两种操作。
修改边权,查找边权的最大值。
分析
我们都知道,树链剖分能够维护点权。
而且每一条边只有一个,且唯一对应一个儿子节点,那么就把信息放到这个儿子节点上。
注意,lca的信息不能算到,也就是当查询到了\(top[u]=top[v]\)的时候,要从\(idx[u]+1\)到\(v\)的查询,因为\(idx[u]\)为lca。
代码
#include <bits/stdc++.h>
#define ms(a, b) memset(a, b, sizeof(a))
#define ll long long
#define ull unsigned long long
#define ms(a, b) memset(a, b, sizeof(a))
#define inf 0x3f3f3f3f
#define db double
#define Pi acos(-1)
#define eps 1e-8
#define N 200005
using namespace std;
template <typename T> void read(T &x) {
x = 0; T fl = 1; char ch = 0;
for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') fl = -1;
for (; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
x *= fl;
}
template <typename T> void write(T x) {
if (x < 0) x = -x, putchar('-');
if (x > 9) write(x / 10); putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) { write(x); puts(""); }
struct edge {
int to, nt, w;
}E[N << 1];
int H[N], top[N], dep[N], son[N], idx[N], fa[N], sz[N], val[N], a[N], U[N], V[N];
int cnt, tot = 0, n;
void add_edge(int u, int v, int w) {
E[++ cnt] = (edge){v, H[u], w};
H[u] = cnt;
}
struct Segment_Tree {
#define lc (nod << 1)
#define rc (nod << 1 | 1)
struct node {
int mx, l, r;
}tr[N << 2];
void pushup(int nod) { tr[nod].mx = max(tr[lc].mx, tr[rc].mx); }
void build(int nod, int l, int r, int *a) {
tr[nod].l = l, tr[nod].r = r; tr[nod].mx = -inf;
if (l == r) { tr[nod].mx = a[l]; return; }
int mid = (l + r) >> 1;
build(lc, l, mid, a); build(rc, mid + 1, r, a);
pushup(nod);
}
void update(int nod, int k, int val) {
int l = tr[nod].l, r = tr[nod].r;
if (l == r) { tr[nod].mx = val; return; }
int mid = (l + r) >> 1;
if (k <= mid) update(lc, k, val); else update(rc, k, val);
pushup(nod);
}
int query(int nod, int ql, int qr) {
int l = tr[nod].l, r = tr[nod].r;
if (ql <= l && r <= qr) return tr[nod].mx;
int mid = (l + r) >> 1, res = -inf;
if (ql <= mid) res = max(res, query(lc, ql, qr));
if (qr > mid) res = max(res, query(rc, ql, qr));
return res;
}
}sgt;
void dfs1(int u, int ft, int dp) {
dep[u] = dp; fa[u] = ft; sz[u] = 1;
int maxson = -1;
for (int e = H[u]; e; e = E[e].nt) {
int v = E[e].to; if (v == fa[u]) continue;
dfs1(v, u, dp + 1);
a[v] = E[e].w; sz[u] += sz[v];
if (sz[v] > maxson) maxson = sz[v], son[u] = v;
}
}
void dfs2(int u, int tp) {
top[u] = tp; idx[u] = ++ tot; val[tot] = a[u];
if (!son[u]) return; dfs2(son[u], tp);
for (int e = H[u]; e; e = E[e].nt) {
int v = E[e].to;
if (v == fa[u] || v == son[u]) continue;
dfs2(v, v);
}
}
char opt[10];
int query_chain(int u, int v) {
int res = -inf;
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
res = max(res, sgt.query(1, idx[top[u]], idx[u]));
u = fa[top[u]];
}
if (dep[u] > dep[v]) swap(u, v);
res = max(res, sgt.query(1, idx[u] + 1, idx[v]));
return res;
}
int main() {
read(n);
for (int i = 1; i < n; i ++) {
int u, v, w; read(u); read(v); read(w);
add_edge(u, v, w); add_edge(v, u, w);
U[i] = u; V[i] = v;
}
dfs1(1, 0, 1); dfs2(1, 1);
sgt.build(1, 1, n, val);
while (scanf("%s", opt) != EOF) {
if (opt[0] == 'D') return 0;
int x, y; read(x); read(y);
if (opt[0] == 'Q') writeln((x != y)? query_chain(x, y): 0);
else {
int u = U[x], v = V[x];
if (fa[v] == u) swap(u, v);
sgt.update(1, idx[u], y);
}
}
return 0;
}
[SPOJ375]QTREE - Query on a tree【树链剖分】的更多相关文章
- spoj QTREE - Query on a tree(树链剖分+线段树单点更新,区间查询)
传送门:Problem QTREE https://www.cnblogs.com/violet-acmer/p/9711441.html 题解: 树链剖分的模板题,看代码比看文字解析理解来的快~~~ ...
- SPOJ QTREE Query on a tree 树链剖分+线段树
题目链接:http://www.spoj.com/problems/QTREE/en/ QTREE - Query on a tree #tree You are given a tree (an a ...
- spoj 375 QTREE - Query on a tree 树链剖分
题目链接 给一棵树, 每条边有权值, 两种操作, 一种是将一条边的权值改变, 一种是询问u到v路径上最大的边的权值. 树链剖分模板. #include <iostream> #includ ...
- SPOJ QTREE Query on a tree ——树链剖分 线段树
[题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #incl ...
- SPOJ QTREE Query on a tree --树链剖分
题意:给一棵树,每次更新某条边或者查询u->v路径上的边权最大值. 解法:做过上一题,这题就没太大问题了,以终点的标号作为边的标号,因为dfs只能给点分配位置,而一棵树每条树边的终点只有一个. ...
- Query on a tree——树链剖分整理
树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...
- SPOJ Query on a tree 树链剖分 水题
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- spoj 375 Query on a tree (树链剖分)
Query on a tree You are given a tree (an acyclic undirected connected graph) with N nodes, and edges ...
- SPOJ375 Query on a tree(树链剖分)
传送门 题意 给出一棵树,每条边都有权值,有两种操作: 把第p条边的权值改为x 询问x,y路径上的权值最大的边 code #include<cstdio> #include<algo ...
- SPOJ 375 Query on a tree 树链剖分模板
第一次写树剖~ #include<iostream> #include<cstring> #include<cstdio> #define L(u) u<&l ...
随机推荐
- YCSB报": No such file or directory"异常
异常信息如下: 文件路径.权限都没有问题. 上网遍寻无果,安装流程与官网一致,开始怀疑是环境问题,后来用别人能用的YCSB复制到本地,却能正常运行. 后来修改了ycsb文件,加了个空格,保存退出,再运 ...
- 简述nginx(1)
Nginx能做什么 1.反向代理 2.负载均衡 3.HTTP服务器(包含动静分离) 4.正向代理 反向代理 反向代理应该是Nginx做的最多的一件事了,什么是反向代理呢,以下是百度百科的说法:反向代理 ...
- Linux的基本解读
Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户.多任务.支持多线程和多CPU的操作系统 而严格来讲,Linux这个词本身只表示Linux内核,但实际上人 ...
- js 判断字符串中是否包含某个字符串的方法实例
String对象的方法 方法一: indexOf() (推荐) var str = "123"; console.log(str.indexOf("3") ...
- mybatis一级缓存详解
mybatis缓存分为一级缓存,二级缓存和自定义缓存.本文重点讲解一级缓存 一:前言 在介绍缓存之前,先了解下mybatis的几个核心概念: * SqlSession:代表和数据库的一次会话,向用户提 ...
- Day 5-<补充> 类的的继承和查找顺序
类的继承于查找顺序: 在py2中,不继承object的类为经典类,经典类继承查找:深度优先. 在py3中,默认继承object,所以python3中都是新式类,新式类的继承查找:广度优先. 类的特殊属 ...
- web跨域请求
第一种情况: 1. sina.com=====>baidu.com/xxx.jsp 也就是前面的域名不相同,(url第三根斜杠之前的内容,也就是主机) 2:localhost =====> ...
- string.Format出现异常:输入字符串的格式不正确 Exception during StringFormat
错误信息:Exception during StringFormat:输入字符串的格式不正确 “System.FormatException”类型的未经处理的异常在 mscorlib.dll 中发生 ...
- Nintex Forms Drop-Down "z-index"
Now we’ve got the issue, that if we are working with a “Person-Column”, the drop-down where you can ...
- React 学习(四) ---- 生命周期函数
现在我们能修改状态,页面可以进行交互了,但是还有一种状态改变没有解决,那就是倒计时效果,时间一直在变化,组件状态也一直在改变,但我们什么都没有做,如果要实现这样的效果,需要怎么处理? 我们都知道,改变 ...