CF487E Tourists - Tarjan缩点 + 树剖 + multiset
Solution
先Tarjan求出点双联通分量 并缩点。 用$multiset$维护 点双内的最小点权。
容易发现, 点双内的最小点权必须包括与它相连的割边的点权。 所以我们必须想办法来维护。
所以考虑用割点的点权更新它的父节点, 这样查询 点双 内的最小点权只需要查询本身的 $multiset$ 和 它的父亲节点就可以了。
最后加个树剖就能过啦!
Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<set> 5 #include<vector> 6 #define rd read() 7 using namespace std; 8 9 const int N = 2e5 + 5; 10 const int inf = ~0U >> 2; 11 12 int Head[N << 1], Tot; 13 int head[N], tot; 14 int low[N], dfn[N], cnt, col, c[N], nd_num, cut[N]; 15 int st[N], tp; 16 int n, m, Q, a[N]; 17 int f[N << 1], top[N << 1], sz[N << 1], son[N << 1], mk, id[N << 1], dep[N << 1]; 18 19 vector<int> q[N]; 20 multiset<int> S[N << 2]; 21 22 struct edge { 23 int nxt, to; 24 }e[N << 2], E[N << 2]; 25 26 int read() { 27 int X = 0, p = 1; char c = getchar(); 28 for (; c > '9' || c < '0'; c = getchar()) 29 if (c == '-') p = -1; 30 for (; c >= '0' && c <= '9'; c = getchar()) 31 X = X * 10 + c - '0'; 32 return X * p; 33 } 34 35 void add(int u, int v) { 36 e[++tot].to = v; 37 e[tot].nxt = head[u]; 38 head[u] = tot; 39 } 40 41 void Add(int u, int v) { 42 E[++Tot].to = v; 43 E[Tot].nxt = Head[u]; 44 Head[u] = Tot; 45 } 46 47 void tarjan(int u) { 48 low[u] = dfn[u] = ++cnt; 49 st[++tp] = u; 50 int flag = 0; 51 for (int i = head[u]; i; i = e[i].nxt) { 52 int nt = e[i].to; 53 if (!dfn[nt]) { 54 tarjan(nt); 55 low[u] = min(low[u], low[nt]); 56 if (low[nt] < dfn[u]) 57 continue; 58 col++; flag++; 59 cut[u] = 1; 60 for (; tp;) { 61 int z = st[tp--]; 62 q[col].push_back(z); 63 if (z == nt) 64 break; 65 } 66 q[col].push_back(u); 67 } 68 else low[u] = min(low[u], dfn[nt]); 69 } 70 if (flag < 2 && u == 1) 71 cut[u] = 0; 72 } 73 74 namespace SegT { 75 76 int MIN[N << 3]; 77 78 #define mid ((l + r) >> 1) 79 #define lson nd << 1 80 #define rson nd << 1 | 1 81 82 void up(int nd) { 83 MIN[nd] = min(MIN[lson], MIN[rson]); 84 } 85 86 void modify(int pos, int d, int l, int r, int nd) { 87 if (l == r) { 88 MIN[nd] = d; 89 return; 90 } 91 if (pos <= mid) 92 SegT::modify(pos, d, l, mid, lson); 93 else 94 SegT::modify(pos, d, mid + 1, r, rson); 95 SegT::up(nd); 96 } 97 int query(int L, int R, int l, int r, int nd) { 98 if (L <= l && r <= R) 99 return MIN[nd]; 100 int tmp = inf; 101 if(L <= mid) 102 tmp = min(tmp, SegT::query(L, R, l, mid, lson)); 103 if(mid < R) 104 tmp = min(tmp, SegT::query(L, R, mid + 1, r, rson)); 105 return tmp; 106 } 107 108 #undef mid 109 #undef lson 110 #undef rson 111 } 112 113 namespace SP { 114 115 void dfs1(int u) { 116 sz[u] = 1; 117 for (int i = Head[u]; i; i = E[i].nxt) { 118 int nt = E[i].to; 119 if (nt == f[u]) 120 continue; 121 f[nt] = u; 122 dep[nt] = dep[u] + 1; 123 SP::dfs1(nt); 124 sz[u] += sz[nt]; 125 if(sz[nt] >= sz[son[u]]) 126 son[u] = nt; 127 } 128 } 129 130 void dfs2(int u) { 131 id[u] = ++mk; 132 if (!son[u]) 133 return; 134 top[son[u]] = top[u]; 135 SP::dfs2(son[u]); 136 for (int i = Head[u]; i; i = E[i].nxt) { 137 int nt = E[i].to; 138 if (nt == f[u] || nt == son[u]) 139 continue; 140 top[nt] = nt; 141 SP::dfs2(nt); 142 } 143 } 144 145 int query(int x, int y) { 146 int re = inf, tmp; 147 for (; top[x] != top[y];) { 148 if (dep[top[x]] < dep[top[y]]) 149 swap(x, y); 150 tmp = SegT::query(id[top[x]], id[x], 1, mk, 1); 151 re = min(tmp, re); 152 x = f[top[x]]; 153 } 154 if (dep[x] < dep[y]) 155 swap(x, y); 156 tmp = SegT::query(id[y], id[x], 1, mk, 1); 157 re = min(tmp, re); 158 if (f[y] && y <= col) 159 tmp = SegT::query(id[f[y]], id[f[y]], 1, mk, 1); 160 re = min(tmp, re); 161 return re; 162 } 163 } 164 165 int main() 166 { 167 n = rd; m = rd; Q = rd; 168 for (int i = 1; i <= n; ++i) 169 a[i] = rd; 170 for (int i = 1; i <= m; ++i) { 171 int u = rd, v = rd; 172 add(u, v); add(v, u); 173 } 174 tarjan(1); 175 nd_num = col; 176 for (int i = 1; i <= n; ++i) 177 if (cut[i]) c[i] = ++nd_num; 178 for (int i = 1; i <= col; ++i) 179 for (int j = 0, len = q[i].size(); j < len; ++j) { 180 int x = q[i][j]; 181 if (cut[x]) 182 Add(c[x], i), Add(i, c[x]); 183 else c[x] = i; 184 } 185 dep[1] = 1; 186 SP::dfs1(1); 187 top[1] = 1; 188 SP::dfs2(1); 189 for (int i = 1; i <= n; ++i) { 190 int x = c[i]; 191 S[x].insert(a[i]); 192 if(x > col) 193 S[f[x]].insert(a[i]); 194 } 195 for (int i = 1; i <= nd_num; ++i) { 196 int x = *S[i].begin(); 197 SegT::modify(id[i], x, 1, mk, 1); 198 } 199 for (; Q; Q--) { 200 char ch = getchar(); 201 while (ch != 'A' && ch != 'C') 202 ch = getchar(); 203 int u = rd, v = rd; 204 if (ch == 'C') { 205 swap(v, a[u]); 206 S[c[u]].erase(S[c[u]].find(v)); 207 S[c[u]].insert(a[u]); 208 int x = *S[c[u]].begin(); 209 SegT::modify(id[c[u]], x, 1, mk, 1); 210 if (c[u] <= col) 211 continue; 212 S[f[c[u]]].erase(S[f[c[u]]].find(v)); 213 S[f[c[u]]].insert(a[u]); 214 x = *S[f[c[u]]].begin(); 215 SegT::modify(id[f[c[u]]], x, 1, mk, 1); 216 } 217 else { 218 if (u == v) printf("%d\n", a[u]); 219 else printf("%d\n", SP::query(c[u], c[v])); 220 } 221 } 222 }