显然只需要维护最大生成树,LCT即可。
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=800010;
void pause()
{
}
int rd()
{
int x=0;
char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x;
}
char rdc()
{
char c=getchar();
while (c<'a'||c>'z') c=getchar();
return c;
}
int fa[maxn],son[maxn][2],sum[maxn],mnid[maxn],inv[maxn],u[maxn],v[maxn],t[maxn],l[maxn],sta[maxn],in[maxn],
n,q,tot;
void down(int u)
{
if (inv[u])
{
swap(son[u][0],son[u][1]);
if (son[u][0]) inv[son[u][0]]^=1;
if (son[u][1]) inv[son[u][1]]^=1;
inv[u]=0;
}
}
void up(int u)
{
sum[u]=sum[son[u][0]]+sum[son[u][1]]+(u>n?l[u-n]:0);
if (mnid[son[u][0]]!=-1&&(mnid[son[u][1]]==-1||t[mnid[son[u][0]]]<t[mnid[son[u][1]]])) mnid[u]=mnid[son[u][0]];
else mnid[u]=mnid[son[u][1]];
if (u>n&&(mnid[u]==-1||t[u-n]<t[mnid[u]])) mnid[u]=u-n;
}
int isroot(int u)
{
return son[fa[u]][0]!=u&&son[fa[u]][1]!=u;
}
void rot(int u,int f)
{
int v=son[u][f],x=son[v][f^1],y=fa[u];
if (son[y][0]==u) son[y][0]=v;
if (son[y][1]==u) son[y][1]=v;
fa[v]=y;
son[v][f^1]=u;
fa[u]=v;
son[u][f]=x;
if (x) fa[x]=u;
up(u);
up(v);
}
void splay(int u)
{
int t=u,x,fx,y,fy,top=0;
while (t)
{
sta[++top]=t;
if (isroot(t)) break;
t=fa[t];
}
for (;top;top--)
down(sta[top]);
while (!isroot(u))
{
x=fa[u];
fx=son[x][1]==u;
if (isroot(x)) rot(x,fx);
else
{
y=fa[x];
fy=son[y][1]==x;
if (fx==fy) rot(y,fy),rot(x,fx);
else rot(x,fx),rot(y,fy);
}
}
}
void access(int u)
{
int v=0,t=u;
while (u)
{
splay(u);
son[u][1]=v;
if (v) fa[v]=u;
up(u);
v=u;
u=fa[u];
}
splay(t);
}
void makeroot(int u)
{
access(u);
inv[u]=1;
}
void link(int u,int v)
{
makeroot(u);
fa[u]=v;
}
void cut(int u,int v)
{
makeroot(u);
access(v);
fa[u]=son[v][0]=0;
up(v);
}
int main()
{
//freopen("b.in","r",stdin);
int x,y,id;
char c;
n=rd();
q=rd();
for (int i=0;i<=n;i++) mnid[i]=-1;
while (q--)
{
c=rdc();
if (c=='f')
{
id=rd()+1;
//if (id==2) pause();
mnid[id+n]=-1;
u[id]=rd()+1;
v[id]=rd()+1;
t[id]=rd();
l[id]=rd();
sum[id+n]=l[id];
mnid[id+n]=id;
makeroot(u[id]);
access(v[id]);
if (!isroot(u[id]))
{
x=mnid[v[id]];
if (t[id]>t[x])
{
cut(u[id],x+n);
cut(v[id],x+n);
link(u[id],id+n);
link(v[id],id+n);
in[x]=0;
in[id]=1;
}
}
else
{
link(u[id],id+n);
link(v[id],id+n);
in[id]=1;
}
}
else if (c=='m')
{
x=rd()+1;
y=rd()+1;
if (x==y)
{
printf("0\n");
continue;
}
makeroot(x);
access(y);
if (!isroot(x)) printf("%d\n",sum[y]);
else printf("-1\n");
}
else
{
id=rd()+1;
x=rd();
if (in[id])
{
cut(u[id],id+n);
cut(v[id],id+n);
sum[id+n]=l[id]=x;
link(u[id],id+n);
link(v[id],id+n);
}
}
}
}