Codeforces 487E 圆方树 + 树链剖分

#include
using namespace std;

const int N = (int)2e5 + 7;
const int inf = 0x3f3f3f3f;

int n, m, q, w[N], pa[N], depth[N];
vector<int> G[N], G2[N];
multiset<int> mulset[N];

int sz[N], son[N], top[N];
int in[N], ot[N], idx;

int bcc_cnt;
int dfn[N], low[N], dfs_clock;
int stk[N], tot;

char op[10];

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
struct SegmentTree {
    int a[N << 2];
    void build(int l, int r, int rt) {
        a[rt] = inf;
        if(l == r) return;
        int mid = l + r >> 1;
        build(lson); build(rson);
    }
    void update(int p, int val, int l, int r, int rt) {
        if(l == r) {
            a[rt] = val;
            return;
        }
        int mid = l + r >> 1;
        if(p <= mid) update(p, val, lson);
        else update(p, val, rson);
        a[rt] = min(a[rt << 1], a[rt << 1 | 1]);
    }
    int query(int L, int R, int l, int r, int rt) {
        if(R < l || r < L || R < L) return inf;
        if(L <= l && r <= R) return a[rt];
        int mid = l + r >> 1;
        return min(query(L, R, lson), query(L, R, rson));
    }
} Tree;

void tarjan(int u, int fa) {
    dfn[u] = low[u] = ++dfs_clock;
    stk[++tot] = u;
    for(auto &v : G[u]) {
        if(v == fa) continue;
        if(!dfn[v]) {
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if(low[v] >= dfn[u]) {
                ++bcc_cnt;
                while(1) {
                    int t = stk[tot--];
                    G2[t].push_back(bcc_cnt);
                    G2[bcc_cnt].push_back(t);
                    mulset[bcc_cnt].insert(w[t]);
                    if(t == v) break;
                }
                G2[u].push_back(bcc_cnt);
                G2[bcc_cnt].push_back(u);
                mulset[bcc_cnt].insert(w[u]);
            }
        }
        else if(dfn[v] < dfn[u]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
}

void dfs(int u, int fa) {
    pa[u] = fa;
    sz[u] = 1;
    son[u] = 0;
    depth[u] = depth[fa] + 1;
    for(auto &v : G[u]) {
        if(v == fa) continue;
        dfs(v, u);
        sz[u] += sz[v];
        if(sz[son[u]] < sz[v]) {
            son[u] = v;
        }
    }
}

void dfs2(int u, int fa, int from) {
    top[u] = from;
    in[u] = ++idx;
    if(son[u]) dfs2(son[u], u, from);
    for(auto &v : G[u]) {
        if(v == fa || v == son[u]) continue;
        dfs2(v, u, v);
    }
    ot[u] = idx;
}

int solve(int u, int v) {
    int ans = inf;
    while(top[u] != top[v]) {
        if(depth[top[u]] < depth[top[v]]) swap(u, v);
        ans = min(ans, Tree.query(in[top[u]], in[u], 1, bcc_cnt, 1));
        u = pa[top[u]];
    }
    if(depth[u] < depth[v]) swap(u, v);
    ans = min(ans, Tree.query(in[v], in[u], 1, bcc_cnt,  1));
    if(v > n) ans = min(ans, w[pa[v]]);
    return ans;
}

int main() {
    scanf("%d%d%d", &n, &m, &q);
    bcc_cnt = n;
    for(int i = 1; i <= n; i++) {
        scanf("%d", &w[i]);
    }
    for(int i = 1; i <= m; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    tarjan(1, 0);
    for(int i = 1; i <= bcc_cnt; i++) {
        G[i] = G2[i];
    }
    dfs(1, 0);
    dfs2(1, 0, 1);
    Tree.build(1, bcc_cnt, 1);
    for(int i = 1; i <= n; i++) {
        Tree.update(in[i], w[i], 1, bcc_cnt, 1);
    }
    for(int i = n + 1; i <= bcc_cnt; i++) {
        mulset[i].insert(inf);
        if(pa[i]) mulset[i].erase(mulset[i].lower_bound(w[pa[i]]));
        Tree.update(in[i], *mulset[i].begin(), 1, bcc_cnt, 1);
    }
    while(q--) {
        int a, b;
        scanf("%s%d%d", op, &a, &b);
        if(*op == 'C') {
            if(pa[a]) mulset[pa[a]].erase(mulset[pa[a]].lower_bound(w[a]));
            w[a] = b;
            if(pa[a]) {
                mulset[pa[a]].insert(w[a]);
                Tree.update(in[pa[a]], *mulset[pa[a]].begin(), 1, bcc_cnt, 1);
            }
            Tree.update(in[a], w[a], 1, bcc_cnt, 1);
        }
        else {
            printf("%d\n", solve(a, b));
        }
    }
    return 0;
}

 

你可能感兴趣的:(Codeforces 487E 圆方树 + 树链剖分)