注意修改的时候要先从上到下减去,然后修改好后从下到上加上。
注意轻边的信息是真的dp值,特判空信息。
顺带,对每条重链单独开线段树会快非常多(代码附后)。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define lint int
#define gc getchar()
#define N 200010
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
int x,ch,sgn=1;while(((ch=gc)<'0'||ch>'9')&&ch!='-');
if(ch=='-') sgn=-1,x=0;else x=ch^'0';
while((ch=gc)>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0');
return x*sgn;
}
struct edges{
int to,pre;
}e[N<<1];int h[N],etop,fa[N],top[N],son[N],in[N];
lint f[N],g[N];int sz[N],vt[N],bot[N],dfs_clock,L[N];
inline int add_edge(int u,int v)
{
return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop;
}
struct answer{
lint w[2][2];bool ept;
answer(lint f=0,lint g=0) { this->init(f,g,1); }
inline lint init(lint f,lint g,bool e)
{ return w[1][1]=f,w[0][0]=g,w[0][1]=w[1][0]=0,ept=e; }
inline answer operator=(const answer &ans)
{ rep(i,0,1) rep(j,0,1) w[i][j]=ans.w[i][j];ept=ans.ept;return *this; }
inline lint f() { return max(w[1][0],w[1][1]); }
inline lint g() { return max(w[0][0],w[0][1]); }
inline lint ans() { return max(f(),g()); }
inline bool empty()const { return ept; }
inline int show()
{ return debug(w[0][0])sp,debug(w[0][1])sp,debug(w[1][0])sp,debug(w[1][1])sp,debug(ept)ln,0; }
}ans;
inline answer merge_ans(const answer &a,const answer &b)
{
if(a.empty()) return b;static answer ans;
ans.init(0,0,0);
rep(i,0,1) rep(j,0,1) rep(p,0,1) rep(q,0,1-p)
ans.w[i][j]=max(ans.w[i][j],a.w[i][p]+b.w[q][j]);
return ans;
}
struct segment{
int l,r;answer ans;
segment *ch[2];
}*rt;
lint build(segment* &rt,int l,int r)
{
rt=new segment,rt->l=l,rt->r=r;int mid=(l+r)>>1;
if(l==r) return rt->ans.init(f[vt[l]],g[vt[r]],0);
build(rt->ch[0],l,mid),build(rt->ch[1],mid+1,r);
return rt->ans=merge_ans(rt->ch[0]->ans,rt->ch[1]->ans),0;
}
inline int push_up(segment* &rt)
{ return rt->ans=merge_ans(rt->ch[0]->ans,rt->ch[1]->ans),0; }
inline int shows(segment* &rt)
{
int l=rt->l,r=rt->r;
if(l<r) shows(rt->ch[0]),shows(rt->ch[1]),push_up(rt);
debug(l)sp,debug(r)sp,rt->ans.show();
return 0;
}
int update(segment* &rt,int p,const answer &v)
{
int l=rt->l,r=rt->r,mid;if(l==r) return rt->ans=v,0;
return mid=(l+r)>>1,update(rt->ch[p>mid],p,v),push_up(rt);
}
int query(segment* &rt,int s,int t)
{
int l=rt->l,r=rt->r,mid=(l+r)>>1;
if(s<=l&&r<=t) return ans=merge_ans(ans,rt->ans),0;
if(s<=mid) query(rt->ch[0],s,t);
if(mid<t) query(rt->ch[1],s,t);
return 0;
}
int update(int x,int v)
{
static answer w;
int c=0;for(int y=top[x];fa[y];y=top[fa[y]]) L[++c]=y;
for(int i=c,y,z;i;i--) y=L[i],z=fa[y],ans.init(0,0,1),
query(rt,in[y],in[bot[y]]),f[z]-=ans.g(),g[z]-=ans.ans();
ans.init(f[x]+=v,g[x],0),update(rt,in[x],ans);
for(int y=top[x],z=fa[y];z;z=fa[y=top[z]])
ans.init(0,0,1),query(rt,in[y],in[bot[y]]),
w.init(f[z]+=ans.g(),g[z]+=ans.ans(),0),update(rt,in[z],w);
return 0;
}
int fir_dfs(int x,int f)
{
fa[x]=f,sz[x]=1,son[x]=0;
for(int i=h[x],y;i;i=e[i].pre)
if((y=e[i].to)^fa[x])
{
fir_dfs(y,x),sz[x]+=sz[y];
if(sz[y]>sz[son[x]]) son[x]=y;
}
return 0;
}
int sec_dfs(int x)
{
vt[in[x]=++dfs_clock]=x;
if(son[x]) top[son[x]]=top[x],sec_dfs(son[x]);
for(int i=h[x],y;i;i=e[i].pre)
if((y=e[i].to)!=fa[x]&&e[i].to!=son[x])
top[y]=y,sec_dfs(y),ans.init(0,0,1),query(rt,in[y],in[bot[y]]),f[x]+=ans.g(),g[x]+=ans.ans();
return ans.init(f[x],g[x],0),update(rt,in[x],ans),bot[x]=(son[x]?bot[son[x]]:x);
}
int main()
{
int n=inn(),q=inn(),x,v;build(rt,1,n);
for(int i=1,u,v;i<n;i++)
u=inn(),v=inn(),add_edge(u,v),add_edge(v,u);
for(int i=1;i<=n;i++) f[i]=inn();
fir_dfs(1,0),top[1]=1,sec_dfs(1);
// for(int i=1;i<=n;i++) debug(i)sp,debug(fa[i])sp,debug(top[i])sp,debug(bot[i])sp,debug(in[i])sp,debug(vt[i])ln;
// for(int i=1;i<=n;i++) debug(i)sp,debug(f[i])sp,debug(g[i])ln;
while(q--)
if(inn()) x=inn(),v=inn(),update(x,v);//update, a[x]+=v
else ans.init(0,0,1),x=inn(),query(rt,in[x],in[bot[x]]),printf("%d\n",ans.ans());
return 0;
}
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define lint int
#define gc getchar()
#define N 200010
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
int x,ch,sgn=1;while(((ch=gc)<'0'||ch>'9')&&ch!='-');
if(ch=='-') sgn=-1,x=0;else x=ch^'0';
while((ch=gc)>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0');
return x*sgn;
}
struct edges{
int to,pre;
}e[N<<1];int h[N],etop,fa[N],top[N],son[N],in[N];
lint f[N],g[N];int sz[N],vt[N],bot[N],dfs_clock,L[N],len[N];
inline int add_edge(int u,int v)
{
return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop;
}
struct answer{
lint w[2][2];bool ept;
answer(lint f=0,lint g=0) { this->init(f,g,1); }
inline lint init(lint f,lint g,bool e)
{ return w[1][1]=f,w[0][0]=g,w[0][1]=w[1][0]=0,ept=e; }
inline answer operator=(const answer &ans)
{ rep(i,0,1) rep(j,0,1) w[i][j]=ans.w[i][j];ept=ans.ept;return *this; }
inline lint f() { return max(w[1][0],w[1][1]); }
inline lint g() { return max(w[0][0],w[0][1]); }
inline lint ans() { return max(f(),g()); }
inline bool empty()const { return ept; }
inline int show()
{ return debug(w[0][0])sp,debug(w[0][1])sp,debug(w[1][0])sp,debug(w[1][1])sp,debug(ept)ln,0; }
}ans;
inline answer merge_ans(const answer &a,const answer &b)
{
if(a.empty()) return b;static answer ans;
ans.init(0,0,0);
rep(i,0,1) rep(j,0,1) rep(p,0,1) rep(q,0,1-p)
ans.w[i][j]=max(ans.w[i][j],a.w[i][p]+b.w[q][j]);
return ans;
}
struct segment{
int l,r;answer ans;
segment *ch[2];
}*rt[N];
lint build(segment* &rt,int l,int r)
{
rt=new segment,rt->l=l,rt->r=r;int mid=(l+r)>>1;if(l==r) return 0;
return build(rt->ch[0],l,mid),build(rt->ch[1],mid+1,r);
}
inline int push_up(segment* &rt)
{ return rt->ans=merge_ans(rt->ch[0]->ans,rt->ch[1]->ans),0; }
inline int shows(segment* &rt)
{
int l=rt->l,r=rt->r;
if(l<r) shows(rt->ch[0]),shows(rt->ch[1]),push_up(rt);
debug(l)sp,debug(r)sp,rt->ans.show();
return 0;
}
int update(segment* &rt,int p,const answer &v)
{
int l=rt->l,r=rt->r,mid;if(l==r) return rt->ans=v,0;
return mid=(l+r)>>1,update(rt->ch[p>mid],p,v),push_up(rt);
}
int query(segment* &rt,int s,int t)
{
int l=rt->l,r=rt->r,mid=(l+r)>>1;
if(s<=l&&r<=t) return ans=merge_ans(ans,rt->ans),0;
if(s<=mid) query(rt->ch[0],s,t);
if(mid<t) query(rt->ch[1],s,t);
return 0;
}
int update(int x,int v)
{
static answer w;
int c=0;for(int y=top[x];fa[y];y=top[fa[y]]) L[++c]=y;
for(int i=c,y,z;i;i--) y=L[i],z=fa[y],ans=rt[y]->ans,f[z]-=ans.g(),g[z]-=ans.ans();
ans.init(f[x]+=v,g[x],0),update(rt[top[x]],in[x],ans);
for(int y=top[x],z=fa[y];z;z=fa[y=top[z]])
ans=rt[y]->ans,w.init(f[z]+=ans.g(),g[z]+=ans.ans(),0),
update(rt[top[z]],in[z],w);
return 0;
}
int fir_dfs(int x,int f)
{
fa[x]=f,sz[x]=1,son[x]=0,len[x]=1;
for(int i=h[x],y;i;i=e[i].pre)
if((y=e[i].to)^fa[x])
{
fir_dfs(y,x),sz[x]+=sz[y];
if(sz[y]>sz[son[x]]) son[x]=y,len[x]=len[y]+1;
}
return 0;
}
int sec_dfs(int x)
{
vt[in[x]=++dfs_clock]=x;
if(x==top[x]) build(rt[x],in[x],in[x]+len[x]-1);
if(son[x]) top[son[x]]=top[x],sec_dfs(son[x]);
for(int i=h[x],y;i;i=e[i].pre)
if((y=e[i].to)!=fa[x]&&e[i].to!=son[x])
top[y]=y,sec_dfs(y),ans=rt[y]->ans,f[x]+=ans.g(),g[x]+=ans.ans();
return ans.init(f[x],g[x],0),update(rt[top[x]],in[x],ans),bot[x]=(son[x]?bot[son[x]]:x);
}
int main()
{
int n=inn(),q=inn(),x,v;
for(int i=1,u,v;i<n;i++)
u=inn(),v=inn(),add_edge(u,v),add_edge(v,u);
for(int i=1;i<=n;i++) f[i]=inn();
fir_dfs(1,0),top[1]=1,sec_dfs(1);
while(q--)
if(inn()) x=inn(),v=inn(),update(x,v);
else ans.init(0,0,1),x=inn(),query(rt[top[x]],in[x],in[bot[x]]),printf("%d\n",ans.ans());
return 0;
}