题目大意:单点加,或者求以1为根时某个点的子树的最大独立集。
题解:
学习了“全局平衡二叉树”这个高级操作。
之前两个log的做发,对每条重链单独开线段树,在luogu的动态dp那个题里跑得比一个log还快,并且通过了加强版。
一个log的做发。
还是类似于两个log的做法,先链分治(树剖),然后现在我们不用线段树维护每一条重链。
我们对一条重链的每个点求其轻子树的size之和再+1,然后每次选择当前链的重心分治建树。这样每个点就对应重链上的一段区间。这样做的好处是:每次经过一条轻边(可以视作连接两条重链对应的树的边),size会减小至少一半;而经过建出来的树的一条边,点对应重链区间对应的连通块大小也会至少减半。因此每次向上跳的总复杂度是O(logn)的。
#include
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define gc getchar()
#define debug(x) cerr<<#x<<"="<
#define sp <<" "
#define ln <
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;
}
#define Max(a,b,c) max(max(a,b),c)
const int N=100010;
struct edges{
int to,pre;
}e[N<<1];int h[N],etop,a[N],f[N],g[N],fq[N],gq[N],in[N],out[N],tms[N],dfc,fa[N],lst[N];
int top[N],sz[N],son[N],szq[N],bot[N];
inline int add_edge(int u,int v) { return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop; }
namespace TREE_SPACE{
int ncnt,fa[N],pre[N],suf[N],pos[N],lc[N],rc[N],id[N];
struct node{
int w00,w01,w10,w11;
node() { w00=w01=w10=w11=0; }
node(int f,int g) { w00=g,w11=f,w01=w10=0; }
inline node operator+(const node &n)const
{
static node t;
t.w00=Max(w00+n.w00,w00+n.w10,w01+n.w00);
t.w01=Max(w00+n.w01,w00+n.w11,w01+n.w01);
t.w10=Max(w10+n.w00,w10+n.w10,w11+n.w00);
t.w11=Max(w10+n.w01,w10+n.w11,w11+n.w01);
return t;
}
inline node operator+=(const node &n) { return (*this)=(*this)+n; }
inline int f()const { return max(w10,w11); }
inline int g()const { return max(w00,w01); }
inline int ans()const { return max(f(),g()); }
inline int show()const { debug(w00)sp,debug(w01)sp,debug(w10)sp,debug(w11)ln;return 0; }
}val[N],s[N];
inline int new_node(int f,int g)
{
int x=++ncnt;fa[x]=lc[x]=rc[x]=0;
val[x]=s[x]=node(f,g);return x;
}
inline int push_up(int x)
{
s[x]=val[x];
if(lc[x]) s[x]=s[lc[x]]+s[x];
if(rc[x]) s[x]=s[x]+s[rc[x]];
return 0;
}
inline int Build(int *f,int *g,int *sz,int l,int r)
{
int p=l;if(l>r) return 0;
pre[l-1]=suf[r+1]=0;rep(i,l,r) pre[i]=pre[i-1]+sz[tms[i]];
for(int i=r;i>=l;i--) suf[i]=suf[i+1]+sz[tms[i]];
rep(i,l+1,r) if(max(pre[i-1],suf[i+1])<max(pre[p-1],suf[p+1])) p=i;
int x=new_node(f[tms[p]],g[tms[p]]);pos[p]=x,id[x]=p;
lc[x]=Build(f,g,sz,l,p-1),rc[x]=Build(f,g,sz,p+1,r);
if(lc[x]) fa[lc[x]]=x;if(rc[x]) fa[rc[x]]=x;return push_up(x),x;
}
node Query(int x,int p)
{
if(id[x]<p) return Query(rc[x],p);
node ans=val[x];if(rc[x]) ans+=s[rc[x]];
if(p<id[x]) ans=Query(lc[x],p)+ans;return ans;
}
struct My_Tree{
int rt;
inline int build(int *f,int *g,int *sz,int l,int r) { return rt=Build(f,g,sz,l,r); }
inline int query(int p) { return Query(rt,p).ans(); }
inline int update(int p,int f,int g) { int x=pos[p];val[x]=node(f,g);while(x) push_up(x),x=fa[x];return 0; }
inline int f() { return s[rt].f(); }
inline int g() { return s[rt].g(); }
inline int ans() { return s[rt].ans(); }
}tr[N];
}
using TREE_SPACE::tr;
int fir_dfs(int x,int fa=0)
{
for(int i=h[x],y;i;i=e[i].pre)
if((y=e[i].to)^fa)
{
sz[x]+=fir_dfs(y,x);
if(sz[y]>sz[son[x]]) son[x]=y;
}
return ++sz[x];
}
int sec_dfs(int x)
{
fq[x]=a[x],gq[x]=0,tms[in[x]=++dfc]=x,szq[x]=1;
if(son[x]) fa[son[x]]=x,top[son[x]]=top[x],sec_dfs(son[x]),bot[x]=bot[son[x]];else bot[x]=x;
for(int i=h[x],y;i;i=e[i].pre) if((y=e[i].to)!=fa[x]&&e[i].to!=son[x])
fa[y]=x,top[y]=y,sec_dfs(y),fq[x]+=g[y],gq[x]+=max(f[y],g[y]),szq[x]+=sz[y];
if(son[x]) f[x]=fq[x]+g[son[x]],g[x]=gq[x]+max(f[son[x]],g[son[x]]);
else f[x]=fq[x],g[x]=gq[x];return out[x]=dfc;
}
inline int upd(int x,int v)
{
int cnt=0;for(int y=top[x];fa[y];y=top[fa[y]]) lst[++cnt]=y;
for(int i=cnt,y,z;i;i--) y=lst[i],z=fa[y],
tr[top[z]].update(in[z],fq[z]-=tr[y].g(),gq[z]-=tr[y].ans());
tr[top[x]].update(in[x],fq[x]+=v,gq[x]);
for(int y=top[x],z=fa[y];z;z=fa[y=top[z]])
tr[top[z]].update(in[z],fq[z]+=tr[y].g(),gq[z]+=tr[y].ans());
return 0;
}
char ss[3000010],tt[20];int ssl,ttl;
inline int show(int x)
{
if(!x) ss[++ssl]='0';for(ttl=0;x;x/=10) tt[++ttl]=char(x%10+'0');
for(;ttl;ttl--) ss[++ssl]=tt[ttl];return ss[++ssl]='\n';
}
int main()
{
int n=inn(),q=inn(),u,v,x;
rep(i,2,n) u=inn(),v=inn(),add_edge(u,v),add_edge(v,u);
rep(i,1,n) a[i]=inn();
fir_dfs(1),top[1]=1,sec_dfs(1);
rep(x,1,n) if(x==top[x]) tr[x].build(fq,gq,szq,in[x],in[bot[x]]);
while(q--)
if(inn()) x=inn(),upd(x,inn());
else x=inn(),printf("%d\n",tr[top[x]].query(in[x]));
return fwrite(ss+1,sizeof(char),ssl,stdout),0;
}