• 洛谷


    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
    ", 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;
    }
    
  • 相关阅读:
    【转】SVN linux命令及 windows相关操作(二)
    【转】SVN linux命令及 windows相关操作(一)
    spring框架DI(IOC)和AOP 原理及方案
    [转载]JVM性能调优--JVM参数配置
    JVM性能调优-GC内存模型及垃圾收集算法
    密码运算API(GP Internal API)
    时间API(GP Internal API)
    可信存储API(GP Internal API)
    内存管理函数(GP Internal API)
    Panic(GP Internal API)
  • 原文地址:https://www.cnblogs.com/Yinku/p/11312626.html
Copyright © 2020-2023  润新知