这个和 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; }