Codeforces 487E 圆方树 + 树链剖分
#include<bits/stdc++.h> 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; }