題目
細節過多。
一對路徑相交當且僅當一個的在另一條路徑上。
所以我們如果詢問一條路徑相交的其他路徑的權值和。
把其他路徑的的,
那麼詢問路徑的權值和就是
考慮維護一個點作爲詢問鏈的時的最大答案。
可以發現所有以爲的答案鏈(圖中綠鏈)可以被分解爲從出發的一條重鏈和一條輕鏈,重鏈下面還接着一個輕鏈,注意我們要求的答案是鏈上的之和,。
也就是說如果我們把一條重鏈看作一個序列,對於每個點把輕鏈中最大的和掛在那個點下面。
那麼就相當於序列上每個點作爲端點有額外的附加值,求最大子段和,這個應該是隨便維護吧(顯然有一堆細節等着你)。
那麼我們把每條重鏈的最大子段和維護好了,再維護一下重鏈的最大子段和中的最大值,那麼就可以輕鬆維護答案了!
那麼每次鏈修改,鏈修改之後點修改,點修改之後上去更新之和的最大值(用維護輕兒子)接着修改。(不要怕)
但是很遺憾的是這個題不是線段樹,而是線段樹套
上面的情況無法考慮重鏈部分只包含個點的情況,因爲會被加兩遍,所以我們需要額外考慮兩個輕鏈組合的情況,因爲我們有區間,所以必須把這個值放在線段樹上才能區間修改後快速取最大值,並且在更新後,在線段樹中找到這個點手動修改後。
#include<bits/stdc++.h>
#define maxn 100005
#define LL long long
using namespace std;
int n,m;
int info[maxn],Prev[maxn<<1],to[maxn<<1],cnt_e;
multiset<LL>ans,xsn[maxn];
void Node(int u,int v){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v; }
LL val[maxn];
LL calc(int u){
if(xsn[u].size() == 0) return 0;
multiset<LL>::iterator it = xsn[u].end();
it --;
LL r = *it;
if(xsn[u].size() == 1) return r;
it--;
return r + *it;
}
struct Seg{
vector<LL>lx,rx,mx,sm,ad,tans,ans,sam;
int len;
void init(int sz){
len = sz;
lx.resize(sz<<2),rx.resize(sz<<2);
sm.resize(sz<<2),mx.resize(sz<<2);
ad.resize(sz<<2),tans.resize(sz<<2);
ans.resize(sz<<2),sam.resize(sz<<2);
}
#define lc u<<1
#define rc lc|1
void dtp(int u,LL v){ ad[u]+=v;rx[u]+=v,mx[u]+=v,ans[u]+=v,tans[u]+=v,sam[u]+=v; }
void dt(int u){ if(ad[u]) dtp(lc,ad[u]),dtp(rc,ad[u]),ad[u]=0; }
void upd(int u){
sm[u] = sm[lc] + sm[rc];
sam[u] = sam[lc] + sam[rc];
lx[u] = max(lx[lc] , lx[rc] + sm[lc]);
rx[u] = max(rx[rc] , rx[lc] + sm[rc]);
mx[u] = max(mx[lc] , max(mx[rc] , lx[rc] + rx[lc]));
tans[u] = max(tans[lc] ,tans[rc]);
ans[u] = max(mx[u] , tans[u]);
}
void add(int u,int l,int r,int p,LL v){
if(l==r) return (void)(lx[u]+=v,sm[u]+=v,sam[u]+=v,rx[u]+=v,tans[u]+=v,ans[u]+=v);
int m=l+r>>1;dt(u);
p <= m ? add(lc,l,m,p,v) : add(rc,m+1,r,p,v);
upd(u);
}
void addl(int u,int l,int r,int p,LL v){
if(l==r) return (void)(lx[u]+=v,rx[u]+=v,ans[u]=max(tans[u],mx[u]));
int m=l+r>>1;dt(u);
p <= m ? addl(lc,l,m,p,v) : addl(rc,m+1,r,p,v);
upd(u);
}
void addp(int u,int l,int r,int ql,int qr,LL v){
if(ql>r||l>qr) return;
if(ql<=l&&r<=qr) return (void)(dtp(u,v));
int m=l+r>>1;dt(u);
addp(lc,l,m,ql,qr,v),addp(rc,m+1,r,ql,qr,v);
upd(u);
}
void mt(int u,int l,int r,int p,int v){
if(l==r){
tans[u] = sam[u] + calc(v);
ans[u] = max(ans[u] , tans[u]);
return;
}
int m=l+r>>1;dt(u);
p <= m ? mt(lc,l,m,p,v) : mt(rc,m+1,r,p,v);
upd(u);
}
}tr[maxn];
int dep[maxn],fa[maxn],tp[maxn],son[maxn],sz[maxn],id[maxn],pos[maxn],ed[maxn],tot;
void dfs1(int u,int ff){
dep[u] = dep[fa[u] = ff] + (sz[u] = 1);
for(int i=info[u],v;i;i=Prev[i]) if((v=to[i])^ff)
dfs1(v,u),sz[u]+=sz[v],(sz[v]>sz[son[u]])&&(son[u]=v);
}
void dfs2(int u,int ff){
pos[id[u] = ++tot] = u;
if(son[u]) tp[son[u]]=tp[u],dfs2(son[u],u);
else ed[tp[u]] = id[u] , ans.insert(0) , tr[tp[u]].init(id[u] - id[tp[u]] + 1);
for(int i=info[u],v;i;i=Prev[i]) if((v=to[i])^ff && v^son[u])
dfs2(tp[v]=v,u),xsn[u].insert(0);
ans.insert(0);
}
void sol(int x,int y,LL w){
for(;tp[x]^tp[y];x=fa[tp[x]]){
if(dep[tp[x]] < dep[tp[y]]) swap(x,y);
ans.erase(ans.find(tr[tp[x]].ans[1]));
tr[tp[x]].addp(1,1,ed[tp[x]]-id[tp[x]]+1,1,id[x]-id[tp[x]]+1,w);
ans.insert(tr[tp[x]].ans[1]);
}
if(dep[x] < dep[y]) swap(x,y);
if(x != y){
ans.erase(ans.find(tr[tp[x]].ans[1]));
tr[tp[x]].addp(1,1,ed[tp[x]]-id[tp[x]]+1,id[y]-id[tp[x]]+2,id[x]-id[tp[x]]+1,w);
ans.insert(tr[tp[x]].ans[1]);
}
val[y] += w;
ans.erase(ans.find(tr[tp[y]].ans[1]));
tr[tp[y]].mt(1,1,tr[tp[y]].len,id[y]-id[tp[y]]+1,y);
ans.insert(tr[tp[y]].ans[1]);
bool f=0;
for(;y;y=fa[tp[y]]){
int p = fa[tp[y]] , t = tp[y]; LL pw = 0;
if(p){
pw = *xsn[p].rbegin();
xsn[p].erase(xsn[p].find(tr[tp[y]].lx[1]));
}
ans.erase(ans.find(tr[tp[y]].ans[1]));
if(!f) tr[tp[y]].add(1,1,ed[tp[y]]-id[tp[y]]+1,id[y]-id[tp[y]]+1,w),f=1;
else tr[tp[y]].addl(1,1,ed[tp[y]]-id[tp[y]]+1,id[y]-id[tp[y]]+1,w);
if(p){
xsn[p].insert(tr[tp[y]].lx[1]);
w = *xsn[p].rbegin() - pw;
ans.erase(ans.find(tr[tp[p]].ans[1]));
tr[tp[p]].mt(1,1,tr[tp[p]].len,id[p]-id[tp[p]]+1,p);
ans.insert(tr[tp[p]].ans[1]);
}
ans.insert(tr[tp[y]].ans[1]);
}
}
int main(){
freopen("3.in","r",stdin);
//freopen("3.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
Node(u,v),Node(v,u);
}
dfs1(1,0),dfs2(tp[1]=1,0);
char ch[2];
static int x[maxn],y[maxn],w[maxn];
for(int i=1;i<=m;i++){
scanf("%s",ch);
if(ch[0] == '+'){
scanf("%d%d%d",&x[i],&y[i],&w[i]);
sol(x[i],y[i],w[i]);
}
else{
int t;
scanf("%d",&t);
sol(x[t],y[t],-w[t]);
}
printf("%lld\n",*ans.rbegin());
}
}