SP375 QTREE - Query on a tree (树剖)

Posted lykkk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SP375 QTREE - Query on a tree (树剖)相关的知识,希望对你有一定的参考价值。

题目

SP375 QTREE - Query on a tree

解析

也就是个蓝题,因为比较长
树剖裸题(基本上),单点修改,链上查询。

可以看到这个题然我们对边进行操作,我们的树剖是对节点进行操作的,所以我们考虑把边权转移到点权上。
技术图片
发现我们节点的点权是连向它的边的边权,所以我们要修改或查询边权的话,我们修改或查询的实际上是其连向点的点权,
假设我们要修改1-4之间的这两条边
技术图片
我们修改的实际上就是这两个点
技术图片
所以我们链上修改或查询的时候,不要修改或查询深度较浅的节点。

然后这是SPOJ上的题,我不知道为啥我写c++会挂,经king丨帝御威大佬的指点才用c过的,%%%

代码

#include <ctype.h>
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#define lson rt << 1
#define rson rt << 1 | 1
#define N 10007
int t, n, m, num, cnt;
int head[N], a[N], w[N], son[N], size[N], f[N], top[N], dep[N], id[N], mx[N << 2];

class node {
    public :
        int nx, v, w;
} e[N << 2];

void add(int u, int v, int w) {
    e[++num].nx = head[u], e[num].v = v, e[num].w = w, head[u] = num;
}

int max(int a, int b) { return a > b ? a : b; }
#define swap(A, B)       {                        int __T = A;         A = B;               B = __T;         }


void dfs1(int u, int fa) {
    size[u] = 1;
    for (int i = head[u]; ~i; i = e[i].nx) {
        int v = e[i].v;
        if (v != fa) {
            dep[v] = dep[u] + 1;
            f[v] = u;
            w[v] = e[i].w;  //边权赋给点
            dfs1(v, u);
            size[u] += size[v];
            if (size[v] > size[son[u]]) son[u] = v;
        }
    }
}

void dfs2(int u, int t) {
    id[u] = ++cnt;
    a[cnt] = w[u];
    top[u] = t;
    if (son[u]) dfs2(son[u], t);
    for (int i = head[u]; ~i; i = e[i].nx) {
        int v = e[i].v;
        if (v != f[u] && v != son[u]) dfs2(v, v);
    }
}

void pushup(int rt) {
    mx[rt] = max(mx[lson], mx[rson]);
}

void build(int l, int r, int rt) {
    if (l == r) {
        mx[rt] = a[l];
        return ;
    }
    int m = (l + r) >> 1;
    build(l, m, lson);
    build(m + 1, r, rson);
    pushup(rt);
}

void update(int L, int c, int l, int r, int rt) {
    if (l == r) {
        mx[rt] = c;
        return ;
    }
    int m = (l + r) >> 1;
    if (L <= m) update(L, c, l, m, lson);
    else update(L, c, m + 1, r, rson);
    pushup(rt);
}

int query(int L, int R, int l, int r, int rt) {
    if (L <= l && r <= R) return mx[rt];
    int m = (l + r) >> 1, ans = -0x3f3f3f3f;
    if (L <= m) ans = max(ans, query(L, R, l, m, lson));
    if (R > m) ans = max(ans, query(L, R, m + 1, r, rson));
    return ans;
}

int query_chain(int x, int y) {
    int fx = top[x], fy = top[y], ans = -0x3f3f3f3f;
    while (fx != fy) {
        if (dep[fx] < dep[fy]) {
            swap(x, y);
            swap(fx, fy);
        }
        ans = max(ans, query(id[fx], id[x], 1, cnt, 1));
        x = f[fx], fx = top[x];
    }
    if (id[x] > id[y]) swap(x, y);
    ans = max(ans, query(id[x] + 1, id[y], 1, cnt, 1));
    /*在这里注意是id[x]+1->id[y]
          不要算上开始的点
        */
    return ans;
}

int main() {
    scanf("%d", &t);
    while (t -- ) {
        num = cnt = 0;
        memset(head, -1, sizeof(head));
        memset(dep, 0, sizeof(dep));
        memset(id, 0, sizeof(id));
        memset(a, 0, sizeof(a));
        memset(w, 0, sizeof(w));
        memset(top, 0, sizeof(top));
        memset(size, 0, sizeof(size));
        memset(e, 0, sizeof(e));
        memset(mx, 0, sizeof(mx));
        memset(son, 0, sizeof(son));
        memset(f, 0, sizeof(f));
        scanf("%d", &n);
        for (int i = 1, x, y, z; i < n; ++i) {
            scanf("%d%d%d", &x, &y, &z);
            add(x, y, z), add(y, x, z);
        }
        dfs1(1, 0), dfs2(1, 1);
        build(1, n, 1);
        char s[20];
        int x, y;
        while (1) {
            scanf("%s", s);
            if (s[0] == 'D') break;
            else if (s[0] == 'C') {
                scanf("%d%d", &x, &y);
                x = dep[e[x << 1].v] > dep[e[(x << 1) - 1].v] ? e[x << 1].v : e[(x << 1) - 1].v;
                /*这里是判断修改哪个点*/
                update(id[x], y, 1, n, 1);
            } else {
                scanf("%d%d", &x, &y);
                printf("%d\\n", query_chain(x, y));
            }
        }
    }
    return 0;
}

以上是关于SP375 QTREE - Query on a tree (树剖)的主要内容,如果未能解决你的问题,请参考以下文章

SP375 QTREE - Query on a tree (树剖)

spoj375 QTREE - Query on a tree

[spoj 375]QTREE - Query on a tree[树链剖分]

SP913 QTREE2 - Query on a tree II

SP16580 QTREE7 - Query on a tree VII

SP913 QTREE2 - Query on a tree II