题解:本题主要考察树链剖分
简要题意:树上操作:
操作 1 :把某个节点
x
x
x的点权增加
a
a
a。
操作 2 :把某个节点
x
x
x为根的子树中所有点的点权都增加
a
a
a。
操作 3 :询问某个节点
x
x
x
1.树链剖分:线段树求区间和与单点修改,区间查询,接下来就是树链剖分的模板
代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
struct N
{
ll ans,lazy;
}t[866006];
struct E
{
ll start,to;
}e[866006];
ll a[666666];
ll siz[200005],d[200005],f[200005],h[200005];
ll top[200005],rk[200005],son[200005],id[200005];
ll n,m,P,num;
void pushup(ll p)
{
t[p].ans=t[p*2].ans+t[p*2+1].ans;
return ;
}
void build(ll p,ll l,ll r)
{
if(l==r){t[p].ans=rk[l];t[p].lazy=0;return ;}
ll mid=l+r>>1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
pushup(p);
}
void lai(ll p,ll l,ll r)
{
ll mid=l+r>>1;
if(t[p].lazy)
{
t[p*2].ans+=t[p].lazy*(mid-l+1);
t[p*2+1].ans+=t[p].lazy*(r-mid);
t[p*2].lazy+=t[p].lazy;
t[p*2+1].lazy+=t[p].lazy;
t[p].lazy=0;
}
return ;
}
void change(ll p,ll l,ll r,ll x,ll y,ll z)
{
if(x<=l&&y>=r)
{
t[p].ans+=z*(r-l+1);
t[p].lazy+=z;
return ;
}
lai(p,l,r);
ll mid=l+r>>1;
if(x<=mid)change(p*2,l,mid,x,y,z);
if(y>mid)change(p*2+1,mid+1,r,x,y,z);
pushup(p);
}
long long ask(ll p,ll l,ll r,ll x,ll y)
{
if(x<=l&&y>=r)return t[p].ans;
lai(p,l,r);
int mid=l+r>>1;
long long ans=0;
if(x<=mid)ans+=ask(p*2,l,mid,x,y);
if(y>mid)ans+=ask(p*2+1,mid+1,r,x,y);
return ans;
}
void add(ll start,ll to)
{
e[++P].to=to;
e[P].start=h[start];
h[start]=P;
}
void dfs1(ll p,ll fa,ll deep)
{
f[p]=fa;siz[p]=1;d[p]=deep;
for(ll i=h[p];i;i=e[i].start)
{
ll k=e[i].to;
if(k==fa)continue;
dfs1(k,p,deep+1);
siz[p]+=siz[k];
if(siz[k]>siz[son[p]])son[p]=k;
}
}
void dfs2(ll p,ll tp)
{
id[p]=++num;rk[num]=a[p];top[p]=tp;
if(!son[p]) return;
dfs2(son[p],tp);
for(ll i=h[p];i;i=e[i].start)
{
ll k=e[i].to;
if(k==f[p]||k==son[p]) continue;
dfs2(k,k);
}
}
long long sum(ll x,ll y)
{
long long ans=0;
while(top[x]!=top[y])
{
if(d[top[x]]<d[top[y]])swap(x,y);
ans+=ask(1,1,n,id[top[x]],id[x]);
x=f[top[x]];
}
if(d[x]>d[y])swap(x,y);
ans+=ask(1,1,n,id[x],id[y]);
return ans;
}
int main()
{
cin>>n>>m;
for(ll i=1;i<=n;i++)cin>>a[i];
for(ll i=1;i<=n-1;i++)
{
ll x,y;
cin>>x>>y;
add(x,y);add(y,x);
}
d[1]=1;
dfs1(1,0,1);dfs2(1,1);
build(1,1,n);
while(m--)
{
ll q,x,y;
cin>>q;
if(q==1)
{
cin>>x>>y;
change(1,1,n,id[x],id[x],y);
}
if(q==2)
{
cin>>x>>y;
change(1,1,n,id[x],id[x]+siz[x]-1,y);
}
if(q==3)
{
cin>>x;
cout<<sum(x,1)<<endl;
}
}
return 0;
}