今天做了一天的LINK-CUT-TREE,非常难受
晚上就只好做点小清新数据结构玩
其实晚上看了半天没看懂,机房dalao随手讲了一下我便恍然大悟
这道题就是一道很裸很裸的链剖,甚至比正常的模版还要水
但是公式十分难推
考虑换根的时候,原来的根(默认为1)到这个根路径以外的点的贡献是不变的
那么对于路径上的点的贡献,洛谷题解的第三篇就讲的很清楚了
所以就贴代码了
// luogu-judger-enable-o2
#include
using namespace std;
struct node
{
node *ls,*rs;
long long sum;
int tag;
}pool[3200005],*tail=pool,*root;
long long sum[200005],ans;
int to[400005],nxt[400005],head[200005];
int size[200005],point[200005],que[200005],dfs_num;
int father[200005],depth[200005],shu1,shu2,shu3;
int n,q,tot,son[200005],top[200005],in[200005],real_sum;
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
void pushdown(node *nd,int l,int r)
{
if(nd->tag)
{
int mid=(l+r)>>1;
nd->ls->tag+=nd->tag;
nd->rs->tag+=nd->tag;
nd->ls->sum+=1ll*(mid-l+1)*nd->tag;
nd->rs->sum+=1ll*(r-mid)*nd->tag;
nd->tag=0;
}
}
void update(node *nd)
{
nd->sum=nd->ls->sum+nd->rs->sum;
}
void dfs1(int x,int fa)
{
size[x]=1;
sum[x]=point[x];
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==fa) continue;
depth[y]=depth[x]+1;
dfs1(y,x);
sum[x]+=sum[y];
size[x]+=size[y];
father[y]=x;
if(size[y]>size[son[x]]) son[x]=y;
}
ans+=1ll*sum[x]*sum[x];
}
void dfs2(int x,int fa,int wow)
{
top[x]=wow;
que[++dfs_num]=x;
in[x]=dfs_num;
if(son[x]) dfs2(son[x],x,wow);
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==fa||y==son[x]) continue;
dfs2(y,x,y);
}
}
void build(node *&nd,int l,int r)
{
nd=tail++;
if(l==r)
{
nd->sum=sum[que[l]];
return;
}
int mid=(l+r)>>1;
build(nd->ls,l,mid);
build(nd->rs,mid+1,r);
update(nd);
}
void modify(node *&nd,int l,int r,int L,int R,int delta)
{
if(l>=L&&r<=R)
{
nd->sum+=(r-l+1)*delta;
nd->tag+=delta;
return;
}
int mid=(l+r)>>1;
pushdown(nd,l,r);
if(mid>=L) modify(nd->ls,l,mid,L,R,delta);
if(midrs,mid+1,r,L,R,delta);
update(nd);
}
long long query(node *nd,int l,int r,int L,int R)
{
if(l>=L&&r<=R)
{
return nd->sum;
}
int mid=(l+r)>>1;
pushdown(nd,l,r);
long long ans=0;
if(mid>=L) ans+=query(nd->ls,l,mid,L,R);
if(midrs,mid+1,r,L,R);
return ans;
}
void modify(int x,int y)
{
int len=0;
long long now=0;
while(x)
{
now+=query(root,1,n,in[top[x]],in[x]);
modify(root,1,n,in[top[x]],in[x],y);
len+=depth[x]-depth[top[x]]+1;
x=father[top[x]];
}
ans+=1ll*len*y*y+2*y*now;
}
long long ask(int x)
{
long long now=0;
int len=0;
while(x)
{
now+=query(root,1,n,in[top[x]],in[x]);
len+=depth[x]-depth[top[x]]+1;
x=father[top[x]];
}
return ans+1ll*(len-1)*real_sum*real_sum-1ll*real_sum*2*(now-real_sum);
}
int main()
{
cin>>n>>q;
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&shu1,&shu2);
add(shu1,shu2);
add(shu2,shu1);
}
for(int i=1;i<=n;i++)
scanf("%d",&point[i]);
dfs1(1,1);
dfs2(1,1,1);
build(root,1,n);
real_sum=sum[1];
for(int i=1;i<=q;i++)
{
scanf("%d",&shu1);
if(shu1==1)
{
scanf("%d%d",&shu2,&shu3);
modify(shu2,shu3-point[shu2]);
real_sum+=shu3-point[shu2];
point[shu2]=shu3;
}
else
{
scanf("%d",&shu2);
printf("%lld\n",ask(shu2));
}
}
return 0;
}