# luogu 3676小清新数据结构题

$\sum_{i\in [p~root]}(s_{i}+\delta)^{2}-\sum_{i\in [p~root]}s_{i}^{2}$

$dep_{p}\delta^{2}+2\delta\sum_{i\in [p~root]}s_{i}$

$ans=ans_{1}-\sum_{i=1}{dep}s_{i}^{2}+\sum_{i=1}^{dep-1}(s_{1}-s_{i+1})^{2}+(s^{'}_{dep})^{2}$

$ans=ans_{1}-\sum_{i=1}^{dep}s_{i}^{2}+deps_{1}^{2}-2s_{1}\sum_{i=2}^{dep}s_{i}+\sum_{i=2}^{dep}s_{i}^{2}$

$ans=ans_{1}+(dep-1)s_{1}^{2}-2s_{1}\sum_{i=1}^{dep}s_{i}+2s_{1}$

$ans=ans_{1}+s_{1}[(dep+1)s_{1}-2\sum_{i=1}^{dep}s_{i}]$

// luogu-judger-enable-o2
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#define rt1 rt<<1
#define rt2 (rt<<1)|1
#define ll long long
using namespace std;
struct Edge
{
int nxt,to;
}edge[400005];
struct Seg_tree
{
ll lazy,sum;
}tree[800005];
int head[200005];
int cnt=1;
int siz[200005],son[200005],nnum[200005],onum[200005],ttop[200005],dep[200005],f[200005];
ll w[200005],s[200005];
int tot;
ll ans=0;
int n,m;
void add(int l,int r)
{
edge[cnt].nxt=head[l];
edge[cnt].to=r;
head[l]=cnt++;
}
void dfs(int x,int fx)
{
siz[x]=1,f[x]=fx,dep[x]=dep[fx]+1,s[x]=w[x];
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(to==fx)continue;
dfs(to,x);
siz[x]+=siz[to],s[x]+=s[to],son[x]=siz[son[x]]<siz[to]?to:son[x];
}
ans+=s[x]*s[x];
}
void redfs(int x,int topx,int fx)
{
ttop[x]=topx,nnum[x]=++tot,onum[tot]=x;
if(son[x])redfs(son[x],topx,x);
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(to==fx||to==son[x])continue;
redfs(to,to,x);
}
}
void buildtree(int rt,int l,int r)
{
if(l==r){tree[rt].sum=s[onum[l]];return;}
int mid=(l+r)>>1;
buildtree(rt1,l,mid),buildtree(rt2,mid+1,r);
tree[rt].sum=tree[rt1].sum+tree[rt2].sum;
}
void pushdown(int rt,int l,int r)
{
tree[rt1].lazy+=tree[rt].lazy,tree[rt2].lazy+=tree[rt].lazy;
int mid=(l+r)>>1;
tree[rt1].sum+=(mid-l+1)*tree[rt].lazy,tree[rt2].sum+=(r-mid)*tree[rt].lazy;
tree[rt].lazy=0;
}
void update(int rt,int l,int r,int lq,int rq,ll v)
{
if(l>=lq&&r<=rq)
{
tree[rt].lazy+=v,tree[rt].sum+=(r-l+1)*v;
return;
}
if(tree[rt].lazy)pushdown(rt,l,r);
int mid=(l+r)>>1;
if(lq<=mid)update(rt1,l,mid,lq,rq,v);
if(rq>mid)update(rt2,mid+1,r,lq,rq,v);
tree[rt].sum=tree[rt1].sum+tree[rt2].sum;
}
ll query(int rt,int l,int r,int lq,int rq)
{
if(l>=lq&&r<=rq)return tree[rt].sum;
int mid=(l+r)>>1;
if(tree[rt].lazy)pushdown(rt,l,r);
ll ret=0;
if(lq<=mid)ret+=query(rt1,l,mid,lq,rq);
if(rq>mid)ret+=query(rt2,mid+1,r,lq,rq);
return ret;
}
void pushup(int x,ll v)
{
while(x){update(1,1,n,nnum[ttop[x]],nnum[x],v),x=f[ttop[x]];}
}
ll l_query(int x)
{
ll ret=0;
while(x){ret+=query(1,1,n,nnum[ttop[x]],nnum[x]),x=f[ttop[x]];}
return ret;
}
template <typename T>inline void read(T &x)
{
T f=1,c=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
x=c*f;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++)
{
int x,y;
read(x),read(y);
add(x,y),add(y,x);
}
for(int i=1;i<=n;i++)read(w[i]);
dfs(1,0),redfs(1,1,1);
buildtree(1,1,n);
while(m--)
{
int typ;
read(typ);
if(typ==1)
{
int x;
ll v;
read(x),read(v);
ans+=(v-w[x])*(v-w[x])*dep[x];
ans+=2*(v-w[x])*l_query(x);
pushup(x,v-w[x]);
w[x]=v;
}else
{
int x;
read(x);
ll temp1=query(1,1,n,nnum[1],nnum[1]);
ll temp2=l_query(x);
ll temps=temp1*((dep[x]+1)*temp1-2*temp2);
printf("%lld\n",ans+temps);
}
}
return 0;
}

posted @ 2019-07-10 08:57  lleozhang  Views(58)  Comments(0Edit  收藏
levels of contents