羅区P2590 [ZJOI2008】統計的問題ツリーツリーチェーンソリューションセグメントツリー分割+

トピックリンク:https://www.luogu.org/problem/P2590
ツリー鋳型鎖分割タイトル。
区のプロセスは、以下の7つの値をとります。

  • fa[u]:U親ノード番号。
  • dep[u]:U深。
  • size[u]:Uをルートとするサブツリー内のノードの総数。
  • son[u]:Uは息子を再度;
  • top[u]:トップノードuの重鎖;
  • seg[u]:U線分ツリー場所;
  • rev[u]:ワンセグが反転し、それがありますrev[seg[u]] == u

次に、最も値、範囲、および更新操作の一点を達成するために、間隔セグメントツリーテンプレートを設定します。

次のようにコードは次のとおりです。

#include <bits/stdc++.h>
using namespace std;
#define INF (1<<29)
const int maxn = 30030;
int fa[maxn],
    dep[maxn],
    size[maxn],
    son[maxn],
    top[maxn],
    seg[maxn], seg_cnt,
    rev[maxn],
    n, w[maxn], maxv[maxn<<2], sumv[maxn<<2];
vector<int> g[maxn];
void dfs1(int u, int p) {
    size[u] = 1;
    for (vector<int>::iterator it = g[u].begin(); it != g[u].end(); it ++) {
        int v = (*it);
        if (v == p) continue;
        fa[v] = u;
        dep[v] = dep[u] + 1;
        dfs1(v, u);
        size[u] += size[v];
        if (size[v] >size[son[u]]) son[u] = v;
    }
}
void dfs2(int u, int tp) {
    seg[u] = ++seg_cnt;
    rev[seg_cnt] = u;
    top[u] = tp;
    if (son[u]) dfs2(son[u], tp);
    for (vector<int>::iterator it = g[u].begin(); it != g[u].end(); it ++) {
        int v = (*it);
        if (v == fa[u] || v == son[u]) continue;
        dfs2(v, v);
    }
}
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1
void push_up(int rt) {
    sumv[rt] = sumv[rt<<1] +sumv[rt<<1|1];
    maxv[rt] = max(maxv[rt<<1], maxv[rt<<1|1]);
}
void build(int l, int r, int rt) {
    int mid = (l + r) / 2;
    if (l == r) {
        sumv[rt] = maxv[rt] = w[rev[l]];
        return;
    }
    build(lson); build(rson);
    push_up(rt);
}
void update(int p, int v, int l, int r, int rt) {
    if (l == r) {
        sumv[rt] = maxv[rt] = v;
        return;
    }
    int mid = (l + r) / 2;
    if (p <= mid) update(p, v, lson);
    else update(p, v, rson);
    push_up(rt);
}
int query_max(int L, int R, int l, int r, int rt) {
    if (L <= l && r <= R) return maxv[rt];
    int mid = (l + r) / 2, tmp = -INF;
    if (L <= mid) tmp = max(tmp, query_max(L, R, lson));
    if (R > mid) tmp = max(tmp, query_max(L, R, rson));
    return tmp;
}
int query_sum(int L, int R, int l, int r, int rt) {
    if (L <= l && r <= R) return sumv[rt];
    int mid = (l + r) / 2, tmp = 0;
    if (L <= mid) tmp += query_sum(L, R, lson);
    if (R > mid) tmp += query_sum(L, R, rson);
    return tmp;
}
int ask_max(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, query_max(seg[top[u]], seg[u], 1, n, 1));
        u = fa[top[u]];
    }
    if (dep[u] < dep[v]) swap(u, v);
    res = max(res, query_max(seg[v], seg[u], 1, n, 1));
    return res;
}
int ask_sum(int u, int v) {
    int res = 0;
    while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
        res += query_sum(seg[top[u]], seg[u], 1, n, 1);
        u = fa[top[u]];
    }
    if (dep[u] < dep[v]) swap(u, v);
    res += query_sum(seg[v], seg[u], 1, n, 1);
    return res;
}
int m;
string s;
int main() {
    cin >> n;
    for (int i = 1; i < n; i ++) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    for (int i = 1; i <= n; i ++) cin >> w[i];
    dep[1] = fa[1] = 1;
    dfs1(1, -1);
    dfs2(1, 1);
    build(1, n, 1);
    cin >> m;
    while (m --) {
        int u, v;
        cin >> s >> u >> v;
        if (s == "CHANGE") update(seg[u], v, 1, n, 1);
        else if (s == "QMAX") cout << ask_max(u, v) << endl;
        else cout << ask_sum(u, v) << endl;
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/codedecision/p/11769437.html