Description
来来来,看看BZOJ极其优美的题面 (滑稽(^o^)/~)
Solution
LCT维护最大生成树的裸题。
三种操作:
1. 加边
- 如果本来两点之间不联通,那么直接连上
- 如果联通,那么判断两点之间的最小值小于新边的边权,那么删去最小的边,加上新边,否则不进行操作。
2. 询问
没什么好说的
3. 更改距离
距离不影响我们的树,直接修改即可。
这题打得挺快的,BZOJ上也AC了,然后UOJ上莫名TLE了Extra Test 5
TM是谁搞了Extra Test这个鬼东西的
于是把之前偷懒写的__gnu_pbds::cc_hash_table
改掉,然后将判是否联通改成并查集就过去了。。。
Source
/************************************************
* Au: Hany01
* Date: Apr 3rd, 2018
* Prob: [BZOJ4736][UOJ274] 温暖会指引我们前行
* Email: hany01@foxmail.com
************************************************/
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
#define File(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout)
#define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i)
#define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define x first
#define y second
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define ALL(a) (a).begin(), (a).end()
#define SZ(a) ((int)(a).size())
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define Mod (1000000007)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define y1 wozenmezhemecaia
template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }
inline int read()
{
register int _, __; register char c_;
for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1;
for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
return _ * __;
}
const int maxn = 100005, maxm = 300005;
int n, len[maxn + maxm], temp[maxn + maxm], eu[maxm], ev[maxm], fa[maxn];
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
struct LCT
{
int fa[maxn + maxm], ch[maxn + maxm][2], mt[maxn + maxm], sl[maxn + maxm], rev[maxn + maxm], id[maxn + maxm];
#define dir(x) (ch[fa[x]][1] == x)
#define isrt(x) (ch[fa[x]][1] != x && ch[fa[x]][0] != x)
inline void pushdown(int u) {
if (rev[u]) rev[u] = 0, rev[ch[u][0]] ^= 1, rev[ch[u][1]] ^= 1, swap(ch[u][0], ch[u][1]);
}
inline void maintain(int u)
{
mt[u] = min(mt[ch[u][0]], min(mt[ch[u][1]], temp[u]));
if (mt[u] == temp[u]) id[u] = u;
else if (mt[u] == mt[ch[u][0]]) id[u] = id[ch[u][0]];
else id[u] = id[ch[u][1]];
sl[u] = sl[ch[u][0]] + sl[ch[u][1]] + len[u];
}
inline void rotate(int u)
{
int f = fa[u], gf = fa[f], d = dir(u);
fa[ch[f][d] = ch[u][d ^ 1]] = f;
fa[u] = gf;
if (!isrt(f)) ch[gf][dir(f)] = u;
ch[u][d ^ 1] = f, fa[f] = u;
maintain(f), maintain(u);
}
int stk[maxn + maxm], top;
inline void splay(int u)
{
stk[top = 1] = u;
for (int t = u; !isrt(t); t = fa[t]) stk[++ top] = fa[t];
while (top) pushdown(stk[top --]);
for ( ; !isrt(u); rotate(u)) if (!isrt(fa[u]))
rotate(dir(u) == dir(fa[u]) ? fa[u] : u);
}
inline void access(int u)
{
for (register int t = 0; u; t = u, u = fa[u])
splay(u), ch[u][1] = t, maintain(u);
}
inline void makeroot(int u) {
access(u), splay(u), rev[u] ^= 1;
}
inline void split(int u, int v) { makeroot(u), access(v), splay(v); }
inline int findroot(int u) {
access(u), splay(u);
while (ch[u][0]) u = ch[u][0];
return u;
}
inline void link(int u, int v) {
//assert(findroot(u) == findroot(v));
makeroot(u), fa[u] = v;
}
inline void cut(int u, int v) { split(u, v), fa[u] = ch[v][0] = 0; }
}lct;
int main()
{
#ifdef hany01
File("bzoj4736");
#endif
static char type[10];
n = read();
Set(lct.mt, 127), Set(temp, 127);
For(i, 1, n) fa[i] = i;
for (static int m = read(); m --; )
{
register int id, u, v;
scanf("%s", type);
if (type[0] == 'f') {
id = read() + 1, u = read() + 1, v = read() + 1, temp[n + id] = read(), len[n + id] = read();
if (u > v) swap(u, v);
eu[id] = u, ev[id] = v;
if (find(u) == find(v))
{
lct.split(u, v);
if (lct.mt[v] < temp[n + id]) {
register int tmp = lct.id[v] - n;
lct.cut(eu[tmp], tmp + n), lct.cut(ev[tmp], tmp + n);
lct.link(u, n + id), lct.link(v, n + id);
}
} else lct.link(u, n + id), lct.link(n + id, v), fa[find(u)] = find(v);
}
else if (type[0] == 'm') {
u = read() + 1, v = read() + 1;
if (find(u) != find(v)) puts("-1");
else {
lct.split(u, v);
if (lct.findroot(v) != u) puts("-1");
else printf("%d\n", lct.sl[v]);
}
} else
id = read() + 1 + n, lct.splay(id), len[id] = read(), lct.maintain(id);
}
return 0;
}
//戚姬髡发入舂市,万古共悲辛。
// -- 李白《中山孺子妾歌》