Solution
由于链信息不好直接维护, 所以新建一个节点存储边的权值, 并把这个节点连向 它所连的节点 $u$, $v$
$pushup$中更新维护的 $mx$ 指向路径上权值最大的边的编号。
由于这题是只有删边, 没有添边, 所以可以离线倒序, 把删边变成添边。
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define rd read() 5 using namespace std; 6 7 const int N = 1e6 + 5; 8 9 int n, m, Q, ans[N]; 10 11 struct edge { 12 int u, v, id, val, d; 13 }e[N]; 14 15 struct que { 16 int typ, u, v, id; 17 }q[N]; 18 19 int read() { 20 int X = 0, p = 1; char c = getchar(); 21 for (; c > '9' || c < '0'; c = getchar()) 22 if (c == '-') p = -1; 23 for (; c >= '0' && c <= '9'; c = getchar()) 24 X = X * 10 + c - '0'; 25 return X * p; 26 } 27 28 namespace LCT { 29 int ch[N][2], f[N], mx[N], tun[N], val[N]; 30 int st[N], tp; 31 #define lc(x) ch[x][0] 32 #define rc(x) ch[x][1] 33 34 int isroot(int x) { 35 return rc(f[x]) != x && 36 lc(f[x]) != x; 37 } 38 39 int get(int x) { 40 return rc(f[x]) == x; 41 } 42 43 void rev(int x) { 44 swap(lc(x), rc(x)); 45 tun[x] ^= 1; 46 } 47 48 void pushdown(int x) { 49 if (tun[x]) { 50 if (lc(x)) rev(lc(x)); 51 if (rc(x)) rev(rc(x)); 52 tun[x] = 0; 53 } 54 } 55 56 void pd(int x) { 57 while (!isroot(x)) { 58 st[++tp] = x; 59 x = f[x]; 60 } 61 st[++tp] = x; 62 while (tp) pushdown(st[tp--]); 63 } 64 65 void up(int x) { 66 mx[x] = val[x]; 67 if (e[mx[lc(x)]].val > e[mx[x]].val) mx[x] = mx[lc(x)]; 68 if (e[mx[rc(x)]].val > e[mx[x]].val) mx[x] = mx[rc(x)]; 69 } 70 71 void rotate(int x) { 72 int old = f[x], oldf = f[old], son = ch[x][get(x) ^ 1]; 73 if (!isroot(old)) ch[oldf][get(old)] = x; 74 ch[x][get(x) ^ 1] = old; 75 ch[old][get(x)] = son; 76 f[x] = oldf; f[old] = x; f[son] = old; 77 up(old); up(x); 78 } 79 80 void splay(int x) { 81 pd(x); 82 for (; !isroot(x); rotate(x)) 83 if (!isroot(f[x])) 84 rotate(get(f[x]) == get(x) ? f[x] : x); 85 } 86 87 void access(int x) { 88 for (int y = 0; x; y = x, x = f[x]) 89 splay(x), ch[x][1] = y, up(x); 90 } 91 92 void mroot(int x) { 93 access(x); 94 splay(x); 95 rev(x); 96 } 97 98 void split(int x, int y) { 99 mroot(x); 100 access(y); 101 splay(y); 102 } 103 104 int findr(int x) { 105 access(x); splay(x); 106 while (lc(x)) pushdown(x), x = lc(x); 107 return x; 108 } 109 110 void link(int x, int y) { 111 mroot(x); f[x] = y; 112 } 113 114 void cut(int x, int y) { 115 split(x, y); 116 f[x] = ch[y][0] = 0; 117 } 118 } 119 using namespace LCT; 120 121 int fd(int x, int y) { 122 int l = 1, r = m; 123 for (; l <= r;) { 124 int mid = (l + r) >> 1; 125 if (e[mid].u < x || (e[mid].u == x && e[mid].v < y)) 126 l = mid + 1; 127 else if (e[mid].u == x && e[mid].v == y) return mid; 128 else r = mid - 1; 129 } 130 return 0; 131 } 132 133 int cmp1(const edge &A, const edge &B) { 134 return A.val < B.val; 135 } 136 137 int cmp2(const edge &A, const edge &B) { 138 return A.u == B.u ? A.v < B.v : A.u < B.u; 139 } 140 141 int cmp3(const edge &A, const edge &B) { 142 return A.id < B.id; 143 } 144 145 int main() 146 { 147 n = rd; m = rd; Q = rd; 148 for (int i = 1; i <= m; ++i) { 149 e[i].u = rd, e[i].v = rd, e[i].val = rd; 150 if (e[i].u > e[i].v) 151 swap(e[i].u, e[i].v); 152 } 153 sort(e + 1, e + 1 + m, cmp1); 154 for (int i = 1; i <= m; ++i) 155 e[i].id = i, val[i + n] = i; 156 sort(e + 1, e + 1 + m, cmp2); 157 for (int i = 1; i <= Q; ++i) { 158 q[i].typ = rd; 159 q[i].u = rd; 160 q[i].v = rd; 161 if (q[i].u > q[i].v) 162 swap(q[i].u, q[i].v); 163 if (q[i].typ == 2) { 164 int t = fd(q[i].u, q[i].v); 165 q[i].id = e[t].id; 166 e[t].d = 1; 167 } 168 } 169 sort(e + 1, e + 1 + m, cmp3); 170 for (int i = 1, tot = 0; i <= m; ++i) if (!e[i].d) { 171 int x = e[i].u, y = e[i].v; 172 mroot(x); 173 if (findr(y) != x) { 174 link(x, i + n); 175 link(y, i + n); 176 tot++; 177 } 178 if (tot == n - 1) break; 179 } 180 for (int i = Q; i; i--) { 181 if (q[i].typ == 1) { 182 split(q[i].u, q[i].v); 183 ans[i] = e[mx[q[i].v]].val; 184 } 185 else { 186 int x = q[i].u, y = q[i].v; 187 mroot(x); 188 if (findr(y) != x) { 189 link(y, q[i].id + n); 190 link(x, q[i].id + n); 191 continue; 192 } 193 if (e[mx[y]].val > e[q[i].id].val) { 194 int t = mx[y]; 195 cut(t + n, e[t].u); 196 cut(t + n, e[t].v); 197 link(q[i].id + n, x); 198 link(q[i].id + n, y); 199 } 200 } 201 } 202 for (int i = 1; i <= Q; ++i) 203 if (q[i].typ == 1) 204 printf("%d ", ans[i]); 205 }