这道题其实是个裸裸的树剖,重点在于怎样处理子树加操作,那么我们在建seq序列时,想办法把一颗子树建的连续起来就好了,那么我们就改变以往的顺序,利用dfs,先跑重链,在跑轻链,这样就把子树建到一起了,然后就非常简单了。话说,这道题跟NOI2015D1T2有什么区别么?
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 100010
using namespace std;
struct yts
{
int l,r;
long long data,tag;
}t[4*maxn];
int to[2*maxn],next[2*maxn],st[maxn],a[maxn];
int dep[maxn],size[maxn],dd[maxn];
int seq[maxn],mx[maxn],pos[maxn],head[maxn],fa[maxn];
int n,m,T,num,id,qwer;
bool vis[maxn];
void addedge(int x,int y)
{
num++;to[num]=y;next[num]=st[x];st[x]=num;
}
void dfs1(int x)
{
size[x]=1;dd[x]=0;
for (int p=st[x];p;p=next[p])
if (to[p]!=fa[x])
{
fa[to[p]]=x;dep[to[p]]=dep[x]+1;
dfs1(to[p]);
size[x]+=size[to[p]];
if (size[to[p]]>size[dd[x]]) dd[x]=to[p];
}
}
void dfs2(int x,int f)
{
head[x]=f;pos[x]=mx[x]=++id;vis[x]=1;
if (dd[x]) dfs2(dd[x],f),mx[x]=max(mx[x],mx[dd[x]]);
for (int p=st[x];p;p=next[p])
if (!vis[to[p]]) dfs2(to[p],to[p]),mx[x]=max(mx[x],mx[to[p]]);
}
void build(int i,int l,int r)
{
t[i].l=l;t[i].r=r;
if (l==r) {t[i].data=a[seq[l]];return;}
int mid=(l+r)/2;
build(i*2,l,mid);build(i*2+1,mid+1,r);
t[i].data=t[i*2].data+t[i*2+1].data;
}
void release(int i)
{
if (t[i].l==t[i].r) return;
if (t[i].tag!=0)
{
long long d=t[i].tag;
t[i*2].tag+=d;t[i*2+1].tag+=d;
t[i*2].data+=d*(t[i*2].r-t[i*2].l+1);
t[i*2+1].data+=d*(t[i*2+1].r-t[i*2+1].l+1);
t[i].tag=0;
}
}
void modify(int i,int l,int r,int x)
{
if (l<=t[i].l && t[i].r<=r) {t[i].data+=(long long)(t[i].r-t[i].l+1)*x;t[i].tag+=x;return;}
release(i);
int mid=(t[i].l+t[i].r)/2;
if (l<=mid) modify(i*2,l,r,x);
if (mid<r) modify(i*2+1,l,r,x);
t[i].data=t[i*2].data+t[i*2+1].data;
}
long long query(int i,int l,int r)
{
if (l<=t[i].l && t[i].r<=r) return t[i].data;
release(i);
int mid=(t[i].l+t[i].r)/2;
long long ans=0;
if (l<=mid) ans+=query(i*2,l,r);
if (mid<r) ans+=query(i*2+1,l,r);
return ans;
}
int main()
{
scanf("%d%d",&n,&T);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
fa[1]=0;dep[1]=0;
dfs1(1);
dfs2(1,1);
for (int i=1;i<=n;i++) seq[pos[i]]=i;
build(1,1,n);
while (T--)
{
int op;
scanf("%d",&op);
if (op==1)
{
int x,a;
scanf("%d%d",&x,&a);
modify(1,pos[x],pos[x],a);
}
if (op==2)
{
int x,a;
scanf("%d%d",&x,&a);
modify(1,pos[x],mx[x],a);
}
if (op==3)
{
int x;
scanf("%d",&x);
long long ans=0;
while (dep[head[x]]>dep[1])
{
ans+=query(1,pos[head[x]],pos[x]);x=fa[head[x]];
}
ans+=query(1,pos[1],pos[x]);
printf("%lld\n",ans);
}
}
return 0;
}