「LuoguP3979」遠い国

ポータル
Luogu

問題解決のためのアイデア

ルートオペレーティング断面変更とツリー。
変更はrootのみの更新またはクエリのサブツリーの情報に影響を与えます。
我々は常に議論の分類限り、その後、同じ元のルートを維持:
現在のノードが照会されると仮定し\(U \)

  1. 場合は\(uが\)直接ツリー全体を尋ねるルートノードは、あります。
  2. 場合は\(uが\)の問い合わせを指示するルートではなく、初期の根の祖先、サブツリーではありません。
  3. 場合は\(uは\)先祖のルーツである、我々は見つける\(U \)このパスのルートにある最初の息子に、そしてあなたが分離することができ、問い合わせ
    クエリ自体はうまくYY分離方法としては。

詳細注意事項

  • GUGU区

参照コード

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <ctime>
#define rg register
using namespace std;
template < typename T > inline void read(T& s) {
    s = 0; int f = 0; char c = getchar();
    while (!isdigit(c)) f |= (c == '-'), c = getchar();
    while (isdigit(c)) s = s * 10 + (c ^ 48), c = getchar();
    s = f ? -s : s;
}

const int _ = 100010;

int tot, head[_], nxt[_ << 1], ver[_ << 1];
inline void Add_edge(int u, int v)
{ nxt[++tot] = head[u], head[u] = tot, ver[tot] = v; }

int n, m, rt, val[_];
int dep[_], siz[_], son[_], fa[_];
int top[_], dfn[_], rev[_];
int mn[_ << 2], tag[_ << 2];

inline int lc(int p) { return p << 1; }

inline int rc(int p) { return p << 1 | 1; }

inline void pushup(int p) { mn[p] = min(mn[lc(p)], mn[rc(p)]); }

inline void f(int p, int v) { mn[p] = tag[p] = v; }

inline void pushdown(int p)
{ if (tag[p]) f(lc(p), tag[p]), f(rc(p), tag[p]), tag[p] = 0; }

inline void build(int p = 1, int l = 1, int r = n) {
    tag[p] = 0; if (l == r) { mn[p] = val[rev[l]]; return ; }
    int mid = (l + r) >> 1;
    build(lc(p), l, mid), build(rc(p), mid + 1, r), pushup(p);
}

inline void update(int ql, int qr, int v, int p = 1, int l = 1, int r = n) {
    if (ql <= l && r <= qr) return f(p, v);
    int mid = (l + r) >> 1;
    pushdown(p);
    if (ql <= mid) update(ql, qr, v, lc(p), l, mid);
    if (qr > mid) update(ql, qr, v, rc(p), mid + 1, r);
    pushup(p);
}

inline int query(int ql, int qr, int p = 1, int l = 1, int r = n) {
    if (ql <= l && r <= qr) return mn[p];
    int mid = (l + r) >> 1, res = 2147483647;
    pushdown(p);
    if (ql <= mid) res = min(res, query(ql, qr, lc(p), l, mid));
    if (qr > mid) res = min(res, query(ql, qr, rc(p), mid + 1, r));
    return res;
}

inline void dfs1(int u, int f) {
    siz[u] = 1, fa[u] = f, dep[u] = dep[f] + 1;
    for (rg int v, i = head[u]; i; i = nxt[i])
        if (!dep[v = ver[i]]) {
            dfs1(v, u), siz[u] += siz[v];
            if (siz[son[u]] < siz[v]) son[u] = v;
        }
}

inline void dfs2(int u, int topf) {
    top[rev[dfn[u] = ++dfn[0]] = u] = topf;
    if (!son[u]) return; dfs2(son[u], topf);
    for (rg int v, i = head[u]; i; i = nxt[i])
        if (!top[v = ver[i]]) dfs2(v, v);
}

inline int pson(int x, int y){
    int fx = top[x], fy = top[y];
    while (fx != fy){
        if (dep[fx] < dep[fy]) swap(x, y), swap(fx, fy);
        if (fa[fx] == y) return fx; x = fa[fx], fx = top[x];
    }
    return dep[x] < dep[y] ? son[x] : son[y];
}

inline int LCA(int x, int y) {
    int fx = top[x], fy = top[y];
    while (fx != fy) {
        if (dep[fx] < dep[fy]) swap(x, y), swap(fx, fy);
        x = fa[fx], fx = top[x];
    }
    return dep[x] < dep[y] ? x : y;
}

inline void uptRange(int x, int y, int v) {
    int fx = top[x], fy = top[y];
    while (fx != fy) {
        if (dep[fx] < dep[fy]) swap(x, y), swap(fx, fy);
        update(dfn[fx], dfn[x], v), x = fa[fx], fx = top[x];
    }
    if (dep[x] > dep[y]) swap(x, y);
    return update(dfn[x], dfn[y], v);
}

inline int qSon(int x) {
    if (rt == x) return query(1, n);
    int lca = LCA(rt, x);
    if (lca != x) return query(dfn[x], dfn[x] + siz[x] - 1);
    int t = pson(rt, x);
    return min(query(1, dfn[t] - 1), query(dfn[t] + siz[t], n));
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
#endif
    read(n), read(m);
    for (rg int u, v, i = 1; i < n; ++i)
        read(u), read(v), Add_edge(u, v), Add_edge(v, u);
    for (rg int i = 1; i <= n; ++i) read(val[i]);
    read(rt), dfs1(rt, 0), dfs2(rt, rt), build();
    for (int opt, x, y, v; m--; ) {
        read(opt);
        if (opt == 1) read(rt);
        else if (opt == 2) read(x), read(y), read(v), uptRange(x, y, v);
        else if (opt == 3) read(x), printf("%d\n", qSon(x));
    }
    return 0;
}

エンドSahua \(qwq \)

おすすめ

転載: www.cnblogs.com/zsbzsb/p/11746535.html