题目描述

给你一棵树,两种操作。
修改边权,查找边权的最大值。

分析

我们都知道,树链剖分能够维护点权。
而且每一条边只有一个,且唯一对应一个儿子节点,那么就把信息放到这个儿子节点上。
注意,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【树链剖分】的更多相关文章

  1. spoj QTREE - Query on a tree(树链剖分+线段树单点更新,区间查询)

    传送门:Problem QTREE https://www.cnblogs.com/violet-acmer/p/9711441.html 题解: 树链剖分的模板题,看代码比看文字解析理解来的快~~~ ...

  2. 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 ...

  3. spoj 375 QTREE - Query on a tree 树链剖分

    题目链接 给一棵树, 每条边有权值, 两种操作, 一种是将一条边的权值改变, 一种是询问u到v路径上最大的边的权值. 树链剖分模板. #include <iostream> #includ ...

  4. SPOJ QTREE Query on a tree ——树链剖分 线段树

    [题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #incl ...

  5. SPOJ QTREE Query on a tree --树链剖分

    题意:给一棵树,每次更新某条边或者查询u->v路径上的边权最大值. 解法:做过上一题,这题就没太大问题了,以终点的标号作为边的标号,因为dfs只能给点分配位置,而一棵树每条树边的终点只有一个. ...

  6. Query on a tree——树链剖分整理

    树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...

  7. SPOJ Query on a tree 树链剖分 水题

    You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

  8. 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 ...

  9. SPOJ375 Query on a tree(树链剖分)

    传送门 题意 给出一棵树,每条边都有权值,有两种操作: 把第p条边的权值改为x 询问x,y路径上的权值最大的边 code #include<cstdio> #include<algo ...

  10. SPOJ 375 Query on a tree 树链剖分模板

    第一次写树剖~ #include<iostream> #include<cstring> #include<cstdio> #define L(u) u<&l ...

随机推荐

  1. 【转】Word之表格、图片的题注(抬头)自动编号

    问:word中的表格怎么自动插入题注(即表头的编号自动编号)? 答: 1首先搞清楚自动编号的意思.自动插入题注的意思是,在你在word中新建或者复制一个word表格的时候,表头的编号就自动生成了,而不 ...

  2. 解决sqoop连接mysq错误

    一.问题描述 1.由于当前集群没有配置Zookeeper.hcatalog.accumlo,因此应该在sqoop的配置文件中注释掉判断Zookeeper.hcatalog.accumlo路径是否正确的 ...

  3. Docker存储驱动Device Mapper,Overlay,AUFS

    Docker存储驱动之Device Mapper简介 - BookShu - 博客园https://www.cnblogs.com/styshoo/p/6528762.html Docker存储驱动之 ...

  4. 理解git工作区和暂存区

    版本库 在工作区目录中有一个.git文件,这个其实不是工作区而是Git的版本库 版本库中包含两个部分,一个是暂存区index/stage,另一个是git自动为我们创建的第一个分支master,以及一个 ...

  5. fastclick的介绍和使用

    移动端点击延迟事件 1. 移动端浏览器在派发点击事件的时候,通常会出现300ms左右的延迟 2. 原因: 移动端的双击会缩放导致click判断延迟 解决方式 1. 禁用缩放 `<meta nam ...

  6. DNS_PROBE_FINISHED_NXDOMAIN & MacOS

    DNS_PROBE_FINISHED_NXDOMAIN 内网 DNS bug 8.8.8.8 8.8.4.4 # new inner Wi-Fi 10.1.3.10 10.1.3.13 Windows ...

  7. Java多线程2:线程的使用及其生命周期

    一.线程的使用方式 1.继承Thread类,重写父类的run()方法 优点:实现简单,只需实例化继承类的实例,即可使用线程 缺点:扩展性不足,Java是单继承的语言,如果一个类已经继承了其他类,就无法 ...

  8. ES 6 系列 - Proxy

    Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以是一种“元编程”,即对编程语言进行编程. 简单地理解,就是在目标对象之前假设一层“拦截”,外界对改对象的访问,都必须先通过这层拦截 ...

  9. Web API2 使用默认Identity

    当您选择个人账户在Web API项目模板,项目包含一个令牌授权服务器验证用户凭证和问题.下面的图显示了相同的凭证流的Web API组件. 发送一个未经授权的请求 首先,运行应用程序并单击按钮调用的AP ...

  10. MongoDB数据模型设计

    MongoDB的数据模式是一种灵活模式,其集合并不限制文档结构.这种灵活性让对象和数据库文档之间的映射变得很容易,即使数据记录之间有很大的变化,每个文档也可以很好的映射到各条不同的记录.但在实际使用中 ...