Given an n-point m-edge graph, the minimum edge between all the simple paths of two points on the graph is obtained.
$ n,m,q \leq 100000, w_i \leq 10 ^7$
# # Solution
Consider establishing a generalized round square tree with a pinch-point pair, and then the value of the square point is the smallest point in the current point double, so that the minimum value on the tree can be maintained directly. But if the update is the root node. Then every son of his party will be updated. So deal with the root node in particular. The checkpoint weight is a point outside the root node. Special treatment can be done.
# # Code
"' CPP
#include <bits/stdc++.h>
using namespace Std;
#define REP (I, A, b) for (int i = (a), i# #_end_ = (b); I <= i# #_end_; ++i)
#define DREP (I, A, b) for (int i = (a), i# #_end_ = (b); I >= i# #_end_; i.)
#define Clar (A, B) memset ((a), (b), sizeof (a))
#define DEBUG (...) fprintf (stderr, __va_args__)
#define DEBUG (s) Debug ("The Massage in line%d, Function%s:%s\n", __line__, __function__, s)
typedef long Long LL;
typedef long double LD;
const int buf_size = (int) 1e6 + 10;
struct FastIO {
Char Buf[buf_size], buf1[buf_size];
int cur, cur1;
FILE *in, *out;
FastIO () {
Cur = buf_size, in = stdin, out = stdout;
Cur1 = 0;
}
inline Char GetChar () {
if (cur = = buf_size) fread (BUF, Buf_size, 1, in), cur = 0;
return * (BUF + (cur++));
}
inline void Putchar (char ch) {
* (Buf1 + (cur1++)) = ch;
if (Cur1 = = buf_size) fwrite (BUF1, Buf_size, 1, out), Cur1 = 0;
}
inline int flush () {
if (Cur1 > 0) fwrite (buf1, Cur1, 1, out);
return cur1 = 0;
}
}io;
#define GETCHAR Io.getchar
#define PUTCHAR Io.putchar
int read () {
char ch = getchar ();
int x = 0, flag = 1;
for (;! IsDigit (CH); ch = getchar ()) if (ch = = '-') flag *=-1;
for (; isdigit (ch); ch = getchar ()) x = x * + ch-48;
return x * flag;
}
void write (int x) {
if (x < 0) Putchar ('-'), x =-X;
if (x >=) write (X/10);
Putchar (x% 10 + 48);
}
void Putstring (char s[], char endchar = ' \ n ') {
Rep (i, 0, strlen (s)-1) Putchar (* (s + i));
if (~endchar) Putchar (EndChar);
}
#define MAXN 300009
struct Edge {
int to, NXT;
}G[MAXN << 1], G1[MAXN << 1];
int n, M, Head[maxn], E, E1, HEAD1[MAXN];
Multiset<int> S[MAXN];
int VAL[MAXN];
int DFN[MAXN], LOW[MAXN], _CLK, cnt_squ;
Stack <int> s;
int TOP[MAXN], DEP[MAXN], SIZE[MAXN], SON[MAXN];
int FA[MAXN], efn[maxn], _index;
Namespace INIT {
void Add (int u, int v) {
G[++e] = (edge) {V, Head[u]}, head[u] = e;
}
void Add1 (int u, int v) {
G1[++E1] = (edge) {V, Head1[u]}, head1[u] = E1;
}
void Tarjan (int u, int fa) {
Dfn[u] = low[u] = ++_CLK;
S.push (U);
for (int i = head[u]; ~i; i = g[i].nxt) {
int v = g[i].to;
if (v! = FA)
if (!dfn[v]) {
Tarjan (V, u);
Low[u] = min (Low[u], low[v]);
if (Low[v] >= Dfn[u]) {
ADD1 (n + (++cnt_squ), u), Add1 (U, n + cnt_squ);
int A;
do {
A = S.top (); S.pop ();
ADD1 (n + cnt_squ, a), Add1 (A, n + cnt_squ);
}while (A! = v);
}
}else Low[u] = min (Low[u], dfn[v]);
}
}
void Dfs_init (int u, int f) {
Size[u] = 1;
Dep[u] = dep[f] + 1, fa[u] = f;
for (int i = head1[u]; ~i; i = g1[i].nxt) {
int v = g1[i].to;
if (v! = f) {
Dfs_init (V, u);
Size[u] + = Size[v];
if (son[u] = = 1 | | size[son[u]] < size[v]) v = son[u];
}
}
}
void Dfs_link (int u, int _top) {
Top[u] = _top;
Dfn[u] = ++_index, Efn[_index] = u;
if (~son[u]) Dfs_link (Son[u], _top);
for (int i = head1[u]; ~i; i = g1[i].nxt) {
int v = g1[i].to;
if (v ^ fa[u] && v ^ son[u]) Dfs_link (V, v);
}
}
void Main () {
Clar (Head,-1);
Clar (Head1,-1);
n = Read (), M = Read ();
Rep (i, 1, n) val[i] = read ();
Rep (i, 1, m) {
int u = Read (), V = read ();
Add (U, v), add (V, u);
}
Tarjan (1, 0);
Clar (DFN, 0), _clk = 0;
Clar (son,-1);
Dfs_init (1, 0);
Dfs_link (1, 1);
Rep (i, 2, N) s[fa[i]-N].insert (Val[i]);
}
}
Namespace Sgmt_tree {
int TREE[MAXN << 2];
#define LC (X) ((x) << 1)
#define RC (x) ((x) << 1 | 1)
#define LS RT << 1, L, mid
#define RS RT << 1 | 1, Mid + 1, r
void pushup (int root) {
Tree[root] = min (TREE[LC (root), TREE[RC (Root)]);
}
void build (int rt, int l, int r) {
if (L = = r) {
TREE[RT] = (Efn[l] <= N)? (Val[efn[l]]): (*s[efn[l]-n].begin ());
return;
}
int mid = (L + r) >> 1;
Build (LS), build (RS);
Pushup (RT);
}
void modify (int rt, int l, int r, int pos) {
if (L = = r) {
TREE[RT] = (Efn[l] <= N)? (Val[efn[l]]): (*s[efn[l]-n].begin ());
Return
}
int mid = (L + r) >> 1;
(Pos <= mid)? Modify (LS, POS): Modify (RS, POS);
Pushup (RT);
}
int query (int rt, int l, int r, int x, int y) {
if (x <= l && r <= y) return tree[rt];
int mid = (L + r) >> 1;
if (Mid >= y) return query (LS, x, y);
if (mid + 1 <= x) return query (RS, x, y);
return min (query (LS, x, y), query (RS, x, y));
}
#undef LC
#undef RC
#undef ls
#undef RS
}
Namespace SOLVE {
void Main () {
int amt = Cnt_squ + N;
Sgmt_tree:: Build (1, 1, AMT);
Rep (I, 1, read ()) {
char s = getchar ();
int x = read (), y = Read ();
if (s = = ' C ') {
if (x > 1) {
S[FA[X]-n].erase (S[fa[x]-n].lower_bound (val[x]));
S[FA[X]-N].insert (y);
Sgmt_tree:: Modify (1, 1, AMT, Dfn[fa[x]);
}
Val[x] = y;
Sgmt_tree:: Modify (1, 1, AMT, Dfn[x]);
}
if (s = = ' Q ') {
int TMP = x, res = Int_max;
while (top[x]! = Top[y]) {
if (Dep[top[x]] < dep[top[y]) swap (x, y);
res = min (res, Sgmt_tree:: Query (1, 1, AMT, Dfn[top[x]], dfn[x]));
x = fa[top[x]];
}
if (Dep[x] < dep[y]) swap (x, y);
res = min (res, Sgmt_tree:: Query (1, 1, AMT, Dfn[x], dfn[y]));
if (x > N) res = min (res, val[fa[x]]);
ASSERT (res! = Int_max);
Write (Val[tmp]-res), Putchar (' \ n ');
}
}
}
}
int main () {
INIT:: Main ();
SOLVE:: Main ();
#ifdef Qrsikno
Debug ("\nrunning Time:%.3lf (s) \ n", clock () * 1.0/clocks_per_sec);
#endif
return Io.flush ();
}
```
[CF Round #278] Tourists