一、题目
二、解法
建议首先看看这道题,基本上是一道题。
现在还剩下的问题就是在换根状态上求 l c a lca lca,首先这个 l c a lca lca一定在 ( u , v ) (u,v) (u,v)的路径上,而路径是不会改变的,通过模拟可以发现 l c a lca lca就是 l c a ( u , v ) lca(u,v) lca(u,v), l c a ( u , l c a ′ ) lca(u,lca') lca(u,lca′), l c a ( v , l c a ′ ) lca(v,lca') lca(v,lca′)其中深度最大的。
#include <cstdio>
#include <iostream>
using namespace std;
#define int long long
const int M = 100005;
int read()
{
int num=0,flag=1;char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=(num<<3)+(num<<1)+(c^48),c=getchar();
return num*flag;
}
int n,m,rt,tot,Index,f[M],a[M],fa[M][20],num[M];
int top[M],dep[M],siz[M],son[M],s[4*M],la[4*M];
struct edge
{
int v,next;
}e[2*M];
void dfs1(int u)
{
siz[u]=1;
dep[u]=dep[fa[u][0]]+1;
for(int i=1;i<20;i++)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=f[u];i;i=e[i].next)
{
int v=e[i].v;
if(v==fa[u][0]) continue;
fa[v][0]=u;
dfs1(v);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
void dfs2(int u,int tp)
{
top[u]=tp;
num[u]=++Index;
if(son[u]) dfs2(son[u],tp);
for(int i=f[u];i;i=e[i].next)
{
int v=e[i].v;
if(v^son[u] && v^fa[u][0]) dfs2(v,v);
}
}
void upd(int i,int l,int r,int v)
{
s[i]+=(r-l+1)*v;
la[i]+=v;
}
void down(int i,int l,int r)
{
if(!la[i]) return ;
int mid=(l+r)>>1;
upd(i<<1,l,mid,la[i]);
upd(i<<1|1,mid+1,r,la[i]);
la[i]=0;
}
void ins(int i,int l,int r,int L,int R,int v)
{
if(L>r || l>R) return ;
if(L<=l && r<=R)
{
upd(i,l,r,v);
return ;
}
down(i,l,r);
int mid=(l+r)>>1;
ins(i<<1,l,mid,L,R,v);
ins(i<<1|1,mid+1,r,L,R,v);
s[i]=s[i<<1]+s[i<<1|1];
}
int ask(int i,int l,int r,int L,int R)
{
if(L>r || l>R) return 0;
if(L<=l && r<=R) return s[i];
down(i,l,r);
int mid=(l+r)>>1;
return ask(i<<1,l,mid,L,R)+ask(i<<1|1,mid+1,r,L,R);
}
int Lca(int u,int v)
{
while(top[u]^top[v])
{
if(dep[top[u]]<dep[top[v]]) swap(u,v);
u=fa[top[u]][0];
}
if(dep[u]>dep[v]) swap(u,v);
return u;
}
int up(int u,int v)
{
for(int i=19;i>=0;i--)
if(dep[fa[v][i]]>dep[u])
v=fa[v][i];
return v;
}
signed main()
{
n=read();m=read();rt=1;
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<n;i++)
{
int u=read(),v=read();
e[++tot]=edge{v,f[u]},f[u]=tot;
e[++tot]=edge{u,f[v]},f[v]=tot;
}
dfs1(1);
dfs2(1,1);
for(int i=1;i<=n;i++)
ins(1,1,n,num[i],num[i],a[i]);
for(int i=1;i<=m;i++)
{
int op=read(),u=read();
if(op==1)
rt=u;
if(op==2)
{
int v=read(),c=read(),lca=Lca(u,v),t1=Lca(u,rt),t2=Lca(v,rt);
if(dep[lca]<dep[t1]) lca=t1;
if(dep[lca]<dep[t2]) lca=t2;
if(lca==rt)
{
ins(1,1,n,1,n,c);
continue;
}
if(num[lca]<=num[rt] && num[rt]<=num[lca]+siz[lca]-1)
{
int t=up(lca,rt);
ins(1,1,n,1,n,c);
ins(1,1,n,num[t],num[t]+siz[t]-1,-c);
}
else
ins(1,1,n,num[lca],num[lca]+siz[lca]-1,c);
}
if(op==3)
{
if(u==rt)
{
printf("%lld\n",ask(1,1,n,1,n));
continue ;
}
if(num[u]<=num[rt] && num[rt]<=num[u]+siz[u]-1)
{
int t=up(u,rt);
printf("%lld\n",ask(1,1,n,1,n)-ask(1,1,n,num[t],num[t]+siz[t]-1));
}
else
printf("%lld\n",ask(1,1,n,num[u],num[u]+siz[u]-1));
}
}
}