题解:
首先一个显然重要的结论是两个链相交当且仅当一个链的lca在另一条链的路径上,或者lca相同。
先链剖,然后我们对于每个点计算以这个点为lca的最大路径,分为两种情况:
1.路径位于两个虚儿子中。这种情况很简单,因为每个点到根只有
O
(
log
n
)
O(\log n)
O(logn)条虚边,每个点维护一个multiset就行了。
2.一条位于实儿子中。每个点到根只有
O
(
log
n
)
O(\log n)
O(logn)个重链,每个重链用数据结构类似最大连续字段和维护一下最长路径即可。
时间复杂度 O ( n log 2 n ) O(n \log^2 n) O(nlog2n)。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
inline void W(LL x) {
static int buf[50];
if(!x) {putchar('0'); return;}
if(x<0) {putchar('-'); x=-x;}
while(x) {buf[++buf[0]]=x%10; x/=10;}
while(buf[0]) {putchar(buf[buf[0]--]+'0');}
}
inline LL Max(multiset <LL> &t) {return (t.size()>=1) ? (*--t.end()) : 0;}
inline LL Sec(multiset <LL> &t) {return (t.size()>=2) ? (*--(--t.end())) : 0;}
const int N=4e5+50;
int n,m,in[N],out[N],id[N],ind;
int fa[N],len[N],top[N],sze[N],son[N],pos[N],dep[N];
int xc[N],yc[N],ww[N];
LL vf[N],virans[N],cans[N];
vector <int> edge[N];
multiset <LL> vir[N];
multiset <LL> ans;
struct ST1 {
int T; LL cans;
LL *lmx,*rmx,*sum,*mxlen;
LL *val_tag,*mxvir;
inline void init(int x) {
T=x; int V=T*4;
lmx=new LL[V]();
rmx=new LL[V]();
sum=new LL[V]();
mxlen=new LL[V]();
val_tag=new LL[V]();
mxvir=new LL[V]();
}
inline void add_val(int k,int w) {rmx[k]+=w; mxlen[k]+=w;}
inline void upt(int k) {
lmx[k]=max(lmx[k<<1],sum[k<<1]+lmx[k<<1|1]);
rmx[k]=max(rmx[k<<1|1],sum[k<<1|1]+rmx[k<<1]);
sum[k]=sum[k<<1]+sum[k<<1|1];
mxlen[k]=max(mxlen[k<<1],mxlen[k<<1|1]);
mxlen[k]=max(mxlen[k],rmx[k<<1]+lmx[k<<1|1]);
}
inline void inc(int k,int l,int r,int L,int R,int w,int type) {
if(L<=l && r<=R) {
if(type==1) {
lmx[k]+=w; rmx[k]+=w; sum[k]+=w;
mxlen[k]=rmx[k];
} else if(type==2) {
w=w-mxvir[k];
lmx[k]+=w; rmx[k]+=w;
mxlen[k]=rmx[k];
mxvir[k]+=w;
} else {
val_tag[k]+=w;
add_val(k,w);
} return;
}
int mid=(l+r)>>1;
if(R<=mid) inc(k<<1,l,mid,L,R,w,type);
else if(L>mid) inc(k<<1|1,mid+1,r,L,R,w,type);
else inc(k<<1,l,mid,L,R,w,type), inc(k<<1|1,mid+1,r,L,R,w,type);
upt(k); add_val(k,val_tag[k]);
}
inline void add(int l,int r,int w,int type) {
ans.erase(ans.find(cans));
inc(1,1,T,l,r,w,type);
ans.insert(cans=mxlen[1]);
}
} rt[N];
struct ST2 {
LL mx[N],val[N];
inline void inc(int k,int l,int r,int L,int R,int w,int type) {
if(L<=l && r<=R) {
if(type==1) mx[k]=w+val[k];
else val[k]+=w, mx[k]+=w;
return;
} int mid=(l+r)>>1;
if(R<=mid) inc(k<<1,l,mid,L,R,w,type);
else if(L>mid) inc(k<<1|1,mid+1,r,L,R,w,type);
else inc(k<<1,l,mid,L,R,w,type), inc(k<<1|1,mid+1,r,L,R,w,type);
mx[k]=max(mx[k<<1],mx[k<<1|1])+val[k];
}
inline LL ask(int k,int l,int r,int L,int R) {
if(L<=l && r<=R) return mx[k];
int mid=(l+r)>>1;
if(R<=mid) return ask(k<<1,l,mid,L,R)+val[k];
else if(L>mid) return ask(k<<1|1,mid+1,r,L,R)+val[k];
else return max(ask(k<<1,l,mid,L,R),ask(k<<1|1,mid+1,r,L,R))+val[k];
}
inline void add(int l,int r,int w,int type) {inc(1,1,n,l,r,w,type);}
inline LL ask(int l,int r) {return ask(1,1,n,l,r);}
} mxg,mxv;
inline void dfs(int x,int f) {
sze[x]=1; fa[x]=f; dep[x]=dep[f]+1;
for(auto v:edge[x]) if(v^f) {
dfs(v,x); sze[x]+=sze[v];
if(sze[v]>sze[son[x]]) son[x]=v;
}
}
inline void Dfs(int x,int f) {
top[x]=f; ++len[f];
in[x]=++ind;
if(son[x]) pos[son[x]]=pos[x]+1, Dfs(son[x],f);
for(auto v:edge[x]) if(v^fa[x] && v^son[x])
pos[v]=1, Dfs(v,v), vir[x].insert(0);
out[x]=ind;
if(x==f) rt[x].init(len[x]), ans.insert(0);
}
inline int lca(int x,int y) {
while(top[x]^top[y]) (dep[top[x]]<dep[top[y]]) ? (y=fa[top[y]]) : (x=fa[top[x]]);
return (dep[x]<dep[y]) ? x : y;
}
inline void opt(int x,int y,int w) {
int l=lca(x,y);
mxg.add(in[l],out[l],w,2);
mxv.add(in[l],in[l],w,2);
rt[top[l]].add(pos[l],pos[l],w,1);
for(int i=top[l];fa[i];i=top[fa[i]]) {
vir[fa[i]].erase(vir[fa[i]].find(vf[i]));
vir[fa[i]].insert(vf[i]=mxg.ask(in[i],out[i])-mxg.ask(in[fa[i]],in[fa[i]]));
rt[top[fa[i]]].add(pos[fa[i]],pos[fa[i]],Max(vir[fa[i]]),2);
mxv.add(in[fa[i]],in[fa[i]],Max(vir[fa[i]])+Sec(vir[fa[i]]),1);
}
for(int i=x;dep[top[i]]>=dep[top[l]];i=fa[top[i]]) {
int L=(top[i]==top[l]) ? in[l]+1 : in[top[i]], R=in[i];
if(L<=R) mxv.add(L,R,w,2), rt[top[i]].add(L-in[top[i]]+1,R-in[top[i]]+1,w,3);
}
for(int i=y;dep[top[i]]>=dep[top[l]];i=fa[top[i]]) {
int L=(top[i]==top[l]) ? in[l]+1 : in[top[i]], R=in[i];
if(L<=R) mxv.add(L,R,w,2), rt[top[i]].add(L-in[top[i]]+1,R-in[top[i]]+1,w,3);
}
}
int main() {
n=rd(), m=rd();
for(int i=1;i<n;i++) {
int x=rd(), y=rd();
edge[x].push_back(y);
edge[y].push_back(x);
} dfs(1,0); pos[1]=1; Dfs(1,1);
for(int i=1;i<=m;i++) {
char ch=nc(); while(isspace(ch)) ch=nc();
if(ch=='+') {
xc[i]=rd(), yc[i]=rd(), ww[i]=rd();
} else {
int t=rd();
xc[i]=xc[t]; yc[i]=yc[t]; ww[i]=-ww[t];
} opt(xc[i],yc[i],ww[i]);
W(max(Max(ans),mxv.mx[1])), putchar('\n');
}
return 0;
}