• 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
    ", query(a));
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    迭代器相关整理
    闭包的功能举例
    函数参数相关整理
    python中进制转换及IP地址转换
    dD Geometry Kernel ( Geometry Kernels) CGAL 4.13 -User Manual
    2D and 3D Linear Geometry Kernel ( Geometry Kernels) CGAL 4.13 -User Manual
    Monotone and Sorted Matrix Search ( Arithmetic and Algebra) CGAL 4.13 -User Manual
    Algebraic Kernel ( Arithmetic and Algebra) CGAL 4.13 -User Manual
    数论中的环概念
    QT的配置及目录结构
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj3083.html
Copyright © 2020-2023  润新知