bzoj3083 遥远的国度

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3083

【题解】

树链剖分,然后换根+询问子树这个是经典套路,分类讨论即可。

复杂度$O(nlog^2n)$

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int N = 1e5 + 10, M = 2e5 + 10, SN = 262144 + 5;
const int mod = 1e9+7, inf = 1e9;

int n, m, d[N], rt;
int head[N], nxt[M], to[M], tot = 0;
inline void add(int u, int v) {
    ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v;
}
inline void adde(int u, int v) {
    add(u, v), add(v, u);
}

int fa[N][18], dep[N], sz[N], son[N];
inline void dfs(int x, int par = 0) {
    fa[x][0] = par; dep[x] = dep[par] + 1;
    sz[x] = 1; son[x] = 0;
    for (int i=1; i<=17; ++i) fa[x][i] = fa[fa[x][i-1]][i-1];
    for (int i=head[x]; i; i=nxt[i]) {
        if(to[i] == par) continue;
        dfs(to[i], x);
        sz[x] += sz[to[i]];
        if(!son[x] || sz[to[i]] > sz[son[x]]) son[x] = to[i];
    }
}

int top[N], seq[N], dfn[N], DFN = 0;
inline void dfs2(int x, int tp, int par = 0) {
    ++DFN; dfn[x] = DFN, seq[DFN] = d[x]; top[x] = tp; 
    if(son[x]) dfs2(son[x], tp, x);
    for (int i=head[x]; i; i=nxt[i])
        if(to[i] != par && to[i] != son[x]) dfs2(to[i], to[i], x);
}

inline int lca(int u, int v) {
    if(dep[u] < dep[v]) swap(u, v);
    for (int i=17; ~i; --i) 
        if((dep[u] - dep[v]) & (1<<i)) u = fa[u][i];
    if(u == v) return u;
    for (int i=17; ~i; --i)
        if(fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
    return fa[u][0];
}

inline int jump(int x, int d) {
    for (int i=17; ~i; --i) 
        if(d & (1<<i)) x = fa[x][i];
    return x;
}
    
struct SMT {
    int w[SN]; int cov[SN]; bool hc[SN];
    # define ls (x<<1)
    # define rs (x<<1|1)
    inline void up(int x) {
        w[x] = min(w[ls], w[rs]);
    }
    inline void pushcov(int x, int cv) {
        hc[x] = 1; cov[x] = cv; w[x] = cv;
    }
    inline void down(int x) {
        if(hc[x]) {
            pushcov(ls, cov[x]);
            pushcov(rs, cov[x]);
            cov[x] = hc[x] = 0;
        }
    }
    inline void build(int x, int l, int r) {
        cov[x] = hc[x] = 0;
        if(l == r) {
            w[x] = seq[l];
            return ;
        }
        int mid = l+r>>1;
        build(ls, l, mid); build(rs, mid+1, r);
        up(x);
    }
    inline void cover(int x, int l, int r, int L, int R, int c) {
        if(L <= l && r <= R) {
            pushcov(x, c);
            return ;
        }
        down(x);
        int mid = l+r>>1;
        if(L <= mid) cover(ls, l, mid, L, R, c);
        if(R > mid) cover(rs, mid+1, r, L, R, c);
        up(x);
    }
    inline int gmin(int x, int l, int r, int L, int R) {
        if(L > R) return inf;
        if(L <= l && r <= R) return w[x];
        down(x);
        int mid = l+r>>1;
        if(R <= mid) return gmin(ls, l, mid, L, R);
        else if(L > mid) return gmin(rs, mid+1, r, L, R);
        else return min(gmin(ls, l, mid, L, R), gmin(rs, mid+1, r, L, R));
    }
    # undef ls
    # undef rs
}T;

inline void modify(int u, int v, int c) {
    while(top[u] != top[v]) {
        if(dep[top[u]] < dep[top[v]]) swap(u, v);
        T.cover(1, 1, n, dfn[top[u]], dfn[u], c);
        u = fa[top[u]][0];
    }
    if(dfn[u] > dfn[v]) swap(u, v);
    T.cover(1, 1, n, dfn[u], dfn[v], c);
}

inline int query(int x) {
    if(rt == x) return T.gmin(1, 1, n, 1, n);
    int p = lca(x, rt);
    if(p != x) return T.gmin(1, 1, n, dfn[x], dfn[x] + sz[x] - 1);
    int D = dep[rt] - dep[x], y = jump(rt, D-1);
    return min(T.gmin(1, 1, n, 1, dfn[y] - 1), T.gmin(1, 1, n, dfn[y] + sz[y], n)); 
}

int main() {
    cin >> n >> m;
    for (int i=1, u, v; i<n; ++i) {
        scanf("%d%d", &u, &v);
        adde(u, v);
    }
    for (int i=1; i<=n; ++i) scanf("%d", d+i);
    scanf("%d", &rt);
    dfs(rt); dfs2(rt, rt);
    T.build(1, 1, n);
    register int opt, a, b, c;
    while(m--) {
        scanf("%d", &opt);
        if(opt == 1) {
            scanf("%d", &a); 
            rt = a;
        } else if(opt == 2) {
            scanf("%d%d%d", &a, &b, &c);
            modify(a, b, c);
        } else {
            scanf("%d", &a);
            printf("%d\n", query(a));
        }
    }
    return 0;
}
View Code

 

posted @ 2017-07-15 19:57  Galaxies  阅读(226)  评论(0编辑  收藏  举报