zoukankan      html  css  js  c++  java
  • [洛谷P2590][ZJOI2008]树的统计

    题目大意:一棵树,支持三个操作,

    $CHANGE;u;t:$ 把结点$u$的权值改为$t$

    $QMAX;u;v:$ 询问从点$u$到点$v$的路径上的节点的最大权值

    $QSUM;u;v:$ 询问从点$u$到点$v$的路径上的节点的权值和

    题解:裸的树链剖分

    卡点:线段树区间修改我不知道哪根筋搭错了,写了$l;==;r$(应为$L;leq;l;&&;R;geq;r$)

    C++ Code:

    #include <cstdio>
    #define maxn 30010
    using namespace std;
    const int inf = 0x3f3f3f3f;
    int n, m;
    int w[maxn], V[maxn << 2], M[maxn << 2];
    inline int max(int a, int b) {return a > b ? a : b;}
    void swap(int &a, int &b) {a ^= b ^= a ^= b;}
    void update(int rt) {
        V[rt] = V[rt << 1] + V[rt << 1 | 1];
        M[rt] = max(M[rt << 1], M[rt << 1 | 1]);
    }
    void build(int rt, int l, int r) {
        if (l == r) {
            V[rt] = M[rt] = w[l];
            return ;
        }
        int mid = l + r >> 1;
        build(rt << 1, l, mid);
        build(rt << 1 | 1, mid + 1, r);
        update(rt);
    }
    void add(int rt, int l, int r, int p, int num) {
        if (l == r) {
            V[rt] = M[rt] = num;
            return ;
        }
        int mid = l + r >> 1;
        if (p <= mid) add(rt << 1, l, mid, p, num);
        else add(rt << 1 | 1, mid + 1, r, p, num);
        update(rt);
    }
    int askS(int rt, int l, int r, int L, int R) {
        if (L <= l && R >= r) {
            return V[rt];
        }
        int mid = l + r >> 1, ans = 0;
        if (L <= mid) ans = askS(rt << 1, l, mid, L, R);
        if (R > mid) ans = ans + askS(rt << 1 | 1, mid + 1, r, L, R);
        return ans;
    }
    int askM(int rt, int l, int r, int L, int R) {
        if (L <= l && R >= r) {
            return M[rt];
        }
        int mid = l + r >> 1, ans = -inf;
        if (L <= mid) ans = askM(rt << 1, l, mid, L, R);
        if (R > mid) ans = max(ans, askM(rt << 1 | 1, mid + 1, r, L, R));
        return ans;
    }
    
    int head[maxn], cnt;
    struct Edge {
        int to, nxt;
    } e[maxn << 1];
    void addE(int a, int b) {
        e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
    }
    int fa[maxn], sz[maxn], son[maxn], dep[maxn];
    int top[maxn], dfn[maxn], idx;
    void dfs1(int rt) {
        sz[rt] = 1;
        for (int i = head[rt]; i; i = e[i].nxt) {
            int v = e[i].to;
            if (v != fa[rt]) {
                dep[v] = dep[rt] + 1;
                fa[v] = rt;
                dfs1(v);
                if (!son[rt] || sz[v] > sz[son[rt]]) son[rt] = v;
                sz[rt] += sz[v];
            }
        }
    }
    void dfs2(int rt) {
        dfn[rt] = ++idx;
        int v = son[rt];
        if (v) top[v] = top[rt], dfs2(v);
        for (int i = head[rt]; i; i = e[i].nxt) {
            v = e[i].to;
            if (v != son[rt] && v != fa[rt]) {
                top[v] = v;
                dfs2(v);
            }
        }
    }
    int queryS(int x, int y) {
        int ans = 0;
        while (top[x] != top[y]) {
            if (dep[top[x]] < dep[top[y]]) swap(x, y);
            ans += askS(1, 1, n, dfn[top[x]], dfn[x]);
            x = fa[top[x]];
        }
        if (dep[x] > dep[y]) swap(x, y);
        ans += askS(1, 1, n, dfn[x], dfn[y]);
        return ans;
    }
    int queryM(int x, int y) {
        int ans = -inf;
        while (top[x] != top[y]) {
            if (dep[top[x]] < dep[top[y]]) swap(x, y);
            ans = max(ans, askM(1, 1, n, dfn[top[x]], dfn[x]));
            x = fa[top[x]];
        }
        if (dep[x] > dep[y]) swap(x, y);
        ans = max(ans, askM(1, 1, n, dfn[x], dfn[y]));
        return ans;
    }
    int main() {
        scanf("%d", &n);
        for (int i = 1; i < n; i++) {
            int a, b;
            scanf("%d%d", &a, &b);
            addE(a, b);
            addE(b, a);
        }
        dep[1] = 1;
        dfs1(1);
        top[1] = 1;
        dfs2(1);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &w[dfn[i]]);
        }
        build(1, 1, n);
        scanf("%d", &m);
        while (m --> 0) {
            char op[10];
            int x, y;
            scanf("%s%d%d", op, &x, &y);
            if (op[1] == 'M') {
                printf("%d
    ", queryM(x, y));
            }
            if (op[1] == 'S') {
                printf("%d
    ", queryS(x, y));
            }
            if (op[1] == 'H') {
                add(1, 1, n, dfn[x], y);
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    asp.net中读取带有加号(+)的Cookie,会自动把加号替换为空格
    简单实现分行输出的javascript代码
    大学我们应该做什么
    近日个人要闻
    WPF学习笔记“路由事件”一:路由事件基础
    WPF学习笔记“路由事件”二:路由事件基础
    WPF学习笔记“命令”三:执行命令
    WPF学习笔记“命令”二:命令库
    WPF学习笔记“命令”五:自定义高级命令的使用
    WPF学习笔记“布局”一:基础
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/9483053.html
Copyright © 2011-2022 走看看