siz[v]表示以v为根的子树的节点数
top[v]表示v所在的重链的顶端节点
fa[v]表示v的父亲
pos[v]表示v的父边标号
mx[v]表示v的子树中边的标号最大的那条边
参考:http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html
题意:
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
第一次写树链剖分。。
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using
namespace
std;
typedef
long
long
LL;
#define N 100010
int
id;
int
fa[N],siz[N],top[N];
int
head[N],pos[N],mx[N],v[N];
LL sum[N<<2],add[N<<2];
struct
Node
{
int
to,next;
}e[N<<1];
int
cnt;
int
n,m;
int
uu,vv;
int
read()
{
int
x=0,f=1;
char
ch=
getchar
();
while
(ch<
‘0‘
||ch>
‘9‘
){
if
(ch==
‘-‘
)f=-1;ch=
getchar
();}
while
(ch>=
‘0‘
&&ch<=
‘9‘
){x=x*10+ch-
‘0‘
;ch=
getchar
();}
return
x*f;
}
void
link(
int
x,
int
y)
{
e[++cnt]=(Node){y,head[x]};
head[x]=cnt;
}
void
dfs(
int
x)
{
siz[x]=1;
for
(
int
i=head[x];i;i=e[i].next)
if
(e[i].to!=fa[x])
{
fa[e[i].to]=x;
dfs(e[i].to);
siz[x]+=siz[e[i].to];
mx[x]=max(mx[x],mx[e[i].to]);
}
}
void
dfs2(
int
x,
int
cha)
{
top[x]=cha;pos[x]=mx[x]=++id;
int
k=0;
for
(
int
i=head[x];i;i=e[i].next)
if
(e[i].to!=fa[x]&&siz[e[i].to]>siz[k])
k=e[i].to;
if
(k)
{
dfs2(k,cha);mx[x]=max(mx[x],mx[k]);
}
for
(
int
i=head[x];i;i=e[i].next)
if
(e[i].to!=fa[x]&&e[i].to!=k)
{
dfs2(e[i].to,e[i].to);
mx[x]=max(mx[x],mx[e[i].to]);
}
}
void
pushup(
int
now)
{
sum[now]=sum[now<<1]+sum[now<<1|1];
}
void
pushdown(
int
nowl,
int
nowr,
int
now)
{
if
(nowl==nowr)
return
;
int
mid=(nowl+nowr)>>1;
LL t=add[now];
add[now]=0;
add[now<<1]+=t;
add[now<<1|1]+=t;
sum[now<<1]+=t*(mid-nowl+1);
sum[now<<1|1]+=t*(nowr-mid);
}
void
update(
int
nowl,
int
nowr,
int
now,
int
l,
int
r,LL d)
{
if
(add[now])
pushdown(nowl,nowr,now);
if
(nowl==l && nowr==r)
{
add[now]+=d;
sum[now]+=(nowr-nowl+1)*d;
return
;
}
int
mid=(nowl+nowr)>>1;
if
(l<=mid)
update(nowl,mid,now<<1,l,min(r,mid),d);
if
(r>mid)
update(mid+1,nowr,now<<1|1,max(l,mid+1),r,d);
pushup(now);
}
LL query(
int
nowl,
int
nowr,
int
now,
int
l,
int
r)
{
if
(add[now])
pushdown(nowl,nowr,now);
if
(nowl==l && nowr==r)
return
sum[now];
int
mid=(nowl+nowr)>>1;
LL ans=0;
if
(l<=mid)
ans+=query(nowl,mid,now<<1,l,min(mid,r));
if
(r>mid)
ans+=query(mid+1,nowr,now<<1|1,max(mid+1,l),r);
return
ans;
}
LL query(
int
x)
{
LL ans=0;
while
(top[x]!=1)
{
ans+=query(1,n,1,pos[top[x]],pos[x]);
x=fa[top[x]];
}
ans+=query(1,n,1,1,pos[x]);
return
ans;
}
int
main()
{
n=read(),m=read();
for
(
int
i=1;i<=n;i++)
v[i]=read();
for
(
int
i=1;i<n;i++)
{
uu=read(),vv=read();
link(uu,vv);
link(vv,uu);
}
dfs(1);
dfs2(1,1);
for
(
int
i=1;i<=n;i++)
update(1,n,1,pos[i],pos[i],v[i]);
int
askd,x,a;
while
(m--)
{
askd=read(),x=read();
if
(askd==1)
{
a=read();
update(1,n,1,pos[x],pos[x],a);
}
if
(askd==2)
{
a=read();
update(1,n,1,pos[x],mx[x],a);
}
if
(askd==3)
printf
(
"%lld\n"
,query(x));
}
return
0;
}
原文:http://www.cnblogs.com/yangjiyuan/p/5328498.html