这个和 QTREE5 的套路是一样的,就是维护一个深度最深/浅的距离和,然后合并一下就好了.
code:
#include <map>
#include <string>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 400008
#define ll long long
using namespace std;
namespace IO {
void setIO(string s)
{
string in=s+".in";
string out=s+".out";
freopen(in.c_str(),"r",stdin);
// freopen(out.c_str(),"w",stdout);
}
};
namespace LCT {
#define lson t[x].ch[0]
#define rson t[x].ch[1]
#define get(x) (t[t[x].f].ch[1]==x)
#define Isr(x) (!(t[t[x].f].ch[0]==x||t[t[x].f].ch[1]==x))
struct node {
int ch[2],rev,f,is_black;
ll son_size,son_dis;
ll size,ldis,rdis,dis,val;
}t[N];
int sta[N];
void Pushup(int x)
{
t[x].size=t[lson].size+t[rson].size+t[x].son_size;
t[x].dis=t[lson].dis+t[rson].dis+t[x].val;
t[x].ldis=t[lson].ldis+t[rson].ldis+t[x].son_dis+(t[x].son_size+t[rson].size)*(t[x].dis-t[rson].dis);
t[x].rdis=t[rson].rdis+t[lson].rdis+t[x].son_dis+(t[x].son_size+t[lson].size)*(t[x].dis-t[lson].dis);
}
void Mark_rev(int x)
{
t[x].rev^=1;
swap(lson,rson);
swap(t[x].ldis,t[x].rdis);
}
void Pushdown(int x)
{
if(t[x].rev)
{
if(lson) Mark_rev(lson);
if(rson) Mark_rev(rson);
t[x].rev^=1;
}
}
void Rotate(int x)
{
int old=t[x].f,fold=t[old].f,which=get(x);
if(!Isr(old)) t[fold].ch[t[fold].ch[1]==old]=x;
t[old].ch[which]=t[x].ch[which^1],t[t[old].ch[which]].f=old;
t[x].ch[which^1]=old,t[old].f=x,t[x].f=fold;
Pushup(old),Pushup(x);
}
void Splay(int x)
{
int v=0,u=x,fa;
for(sta[++v]=u;!Isr(u);u=t[u].f) sta[++v]=t[u].f;
for(;v;--v) Pushdown(sta[v]);
for(u=t[u].f;(fa=t[x].f)!=u;Rotate(x))
if(t[fa].f!=u)
Rotate(get(fa)==get(x)?fa:x);
}
void Access(int x)
{
for(int y=0;x;y=x,x=t[x].f)
{
Splay(x);
if(rson)
{
t[x].son_size+=t[rson].size;
t[x].son_dis+=t[rson].ldis;
}
if(y)
{
t[x].son_size-=t[y].size;
t[x].son_dis-=t[y].ldis;
}
rson=y;
Pushup(x);
}
}
void Make_Root(int x)
{
Access(x),Splay(x),Mark_rev(x);
}
void Link_Edge(int x,int y)
{
Access(x),Splay(x);
Make_Root(y);
t[y].f=x;
t[x].son_size+=t[y].size;
t[x].son_dis+=t[y].ldis;
}
void Cut_Edge(int x,int y)
{
Make_Root(x);
Access(y),Splay(y);
t[y].ch[0]=t[x].f=0;
Pushup(y);
}
};
map<int,int>tr[N];
int main()
{
// IO::setIO("input");
using namespace LCT;
int i,j,n,m,q,tot;
scanf("%d%d%d",&n,&m,&q);
tot=n;
for(i=1;i<=m;++i)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
tr[x][y]=tr[y][x]=++tot;
LCT::t[tot].val=w;
LCT::Link_Edge(x,tot);
LCT::Link_Edge(y,tot);
}
for(i=1;i<=q;++i)
{
char str[3];
scanf("%s",str);
if(str[0]=='L')
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
tr[x][y]=tr[y][x]=++tot;
LCT::t[tot].val=w;
LCT::Link_Edge(x,tot);
LCT::Link_Edge(y,tot);
}
if(str[0]=='C')
{
int x,y,key=0;
scanf("%d%d",&x,&y);
key=tr[x][y];
LCT::Cut_Edge(x,key);
LCT::Cut_Edge(y,key);
}
if(str[0]=='F')
{
int x;
scanf("%d",&x);
LCT::Access(x);
LCT::Splay(x);
LCT::t[x].is_black^=1;
if(LCT::t[x].is_black==0)
{
--t[x].son_size;
}
else
{
++t[x].son_size;
}
LCT::Pushup(x);
}
if(str[0]=='Q')
{
int x;
scanf("%d",&x);
LCT::Make_Root(x);
Access(x);
printf("%lld\n",LCT::t[x].son_dis);
}
}
return 0;
}