1. 程式人生 > >SP375 QTREE - Query on a tree (樹剖)

SP375 QTREE - Query on a tree (樹剖)

cpp 圖片 操作 bubuko query push img eof 深度

題目

SP375 QTREE - Query on a tree

解析

也就是個藍題,因為比較長
樹剖裸題(基本上),單點修改,鏈上查詢。

順便來說一下鏈上操作時如何將邊上的操作轉化為點上的操作:
可以看到這個題然我們對邊進行操作,我們的樹剖是對節點進行操作的,所以我們考慮把邊權變為點權。
技術分享圖片
發現我們節點的點權是連向它的邊的邊權,所以我們要操作邊權的話,我們操作的實際上是其連向點的點權,
假設我們要修改1-4之間的這兩條邊
技術分享圖片
我們修改的實際上就是這2,4兩個點
技術分享圖片
我們節點的點權為其父節點連向它的邊的邊權,所以我們鏈上修操作的時候,不要操作深度較低的節點,因為它代表的邊是它的父節點連向它的那一條,不是要操作的兩點之間的邊,就像上圖我們不操作1號節點一樣。

不用特意判斷;兩個位置的深淺,樹剖中會判斷,詳見這裏

再說一下這個題的修改,因為我們是要修改邊權,我們的邊權給了點,所以我們找一下這條邊連的兩個點,判斷兩個點的深度,較深的那個是我們要修改的點。

然後這是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;
                /*因為是無向邊,加了兩次,兩次的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 (樹剖)