有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
这道题不会正解,树链剖分水过。
因为我太弱,LL和int ;%lld和%I64d没分清,调了一晚。
#include<iostream>
#include<cstdio>
#include<algorithm>
#define LL long long
#define maxn 100006
using namespace std;
struct bian{int to;}b[200006];
int fst[maxn],nxt[200006],tot=0;
void build(int f,int t)
{
b[++tot].to=t;
nxt[tot]=fst[f];
fst[f]=tot;
}
//===================================================
int zson[maxn],fa[maxn];
int sz[maxn],sd[maxn];
void dfs1(int x)
{
int v,ans=0;
sz[x]++;
for(int i=fst[x];i;i=nxt[i])
{
v=b[i].to;
if(!sd[v])
{
sd[v]=sd[x]+1;
fa[v]=x;
dfs1(v);
sz[x]+=sz[v];
if(sz[v]>ans)
{
ans=sz[v];
zson[x]=v;
}
}
}
}
LL w[100006];
int intr[maxn],top[maxn];
int in[maxn],out[maxn];
int dfs_c;
void dfs2(int x,int u)
{
top[x]=u;
in[x]=++dfs_c;
intr[dfs_c]=x;
if(zson[x]) dfs2(zson[x],u);
int v;
for(int i=fst[x];i;i=nxt[i])
{
v=b[i].to;
if(!top[v])
dfs2(v,v);
}
out[x]=dfs_c;
}
//===================================================
struct xds
{
LL sum,add;
int l,r;
}tree[maxn<<2];
void up(int dq)
{tree[dq].sum=tree[dq<<1].sum+tree[dq<<1|1].sum;}
void build(int dq,int l,int r)
{
tree[dq].l=l;
tree[dq].r=r;
if(l==r)
{
tree[dq].sum=w[intr[l]];
return ;
}
int mid=(l+r)>>1;
build(dq<<1,l,mid);
build(dq<<1|1,mid+1,r);
up(dq);
}
void spread(int dq)
{
if(tree[dq].add)
{
LL add=tree[dq].add;
tree[dq<<1].add+=add;
tree[dq<<1|1].add+=add;
tree[dq<<1].sum+=(tree[dq<<1].r-tree[dq<<1].l+1)*add;
tree[dq<<1|1].sum+=(tree[dq<<1|1].r-tree[dq<<1|1].l+1)*add;
tree[dq].add=0;
}
}
void change(int dq,int l,int r,LL d)
{
if(tree[dq].l>=l&&tree[dq].r<=r)
{
tree[dq].add+=d;
tree[dq].sum+=(tree[dq].r-tree[dq].l+1)*d;
return ;
}
spread(dq);
int mid=(tree[dq].l+tree[dq].r)>>1;
if(mid>=l)
change(dq<<1,l,r,d);
if(mid<r)
change(dq<<1|1,l,r,d);
up(dq);
}
LL ask(int dq,int l,int r)
{
if(tree[dq].l>=l&&tree[dq].r<=r)
return tree[dq].sum;
spread(dq);LL ans=0;
int mid=(tree[dq].l+tree[dq].r)>>1;
if(mid>=l)
ans+=ask(dq<<1,l,r);
if(mid<r)
ans+=ask(dq<<1|1,l,r);
up(dq);
return ans;
}
LL find(int x)
{
LL ans=0;
int fx;
while(true)
{
fx=top[x];
ans+=ask(1,in[fx],in[x]);
x=top[x];
if(x!=1)x=fa[x];
else break;
}
return ans;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&w[i]);
int f,t;
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&f,&t);
build(f,t);
build(t,f);
}
fa[1]=1;
sd[1]=1;dfs1(1);
dfs2(1,1);
build(1,1,n);
int op,x;
LL a;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&op,&x);
if(op==3)
printf("%lld\n",find(x));
else
{
scanf("%lld",&a);
if(op==1)change(1,in[x],in[x],a);
else change(1,in[x],out[x],a);
}
}
}