树链剖分裸题
ps:pushdown的时候区间长度(r-l+1)打成(r-r+1)居然过了样例+手造数据,害我自闭了好久qwq
/**************************************************************
Problem: 4034
User: syh0313
Language: C++
Result: Accepted
Time:2500 ms
Memory:21628 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <string>
#define lch a[n].lc
#define rch a[n].rc
using
namespace
std;
const
int
maxe=200010;
const
int
maxd=100010;
int
n,m,topt,nt[maxe],st[maxe],to[maxe];
long
long
v[maxd];
int
fa[maxd],size[maxd],rem[maxd];
int
dfn[maxd],dfn_num,line[maxd],top[maxd];
struct
tree
{
int
l,r,lc,rc;
long
long
sum,tag;
}a[maxe<<1];
int
cnt,root;
bool
f[maxd];
void
add(
int
x,
int
y)
{to[++topt]=y; nt[topt]=st[x]; st[x]=topt;}
void
dfs1(
int
x)
{
int
p=st[x],ma=0; f[x]=1; size[x]=1;
while
(p)
{
if
(!f[to[p]])
{
dfs1(to[p]);
fa[to[p]]=x;
size[x]+=size[to[p]];
if
(size[to[p]]>ma) {ma=size[to[p]]; rem[x]=to[p];}
}
p=nt[p];
}
}
void
dfs2(
int
x)
{
f[x]=1;
if
(rem[fa[x]]==x) top[x]=top[fa[x]];
else
top[x]=x;
dfn[++dfn_num]=x; line[x]=dfn_num;
if
(rem[x]) dfs2(rem[x]);
int
p=st[x];
while
(p)
{
if
(!f[to[p]]) dfs2(to[p]);
p=nt[p];
}
}
void
updata(
int
n)
{a[n].sum=a[lch].sum+a[rch].sum;}
void
build_tree(
int
&n,
int
l,
int
r)
{
n=++cnt; a[n].l=l; a[n].r=r;
if
(l==r) {a[n].sum=v[dfn[l]];
return
;}
int
mid=(l+r)>>1;
build_tree(lch,l,mid);
build_tree(rch,mid+1,r);
updata(n);
}
void
pushdown(
int
n)
{
if
(a[n].tag)
{
if
(lch)
{
a[lch].tag+=a[n].tag;
a[lch].sum+=1ll*(a[lch].r-a[lch].l+1)*a[n].tag;
}
if
(rch)
{
a[rch].tag+=a[n].tag;
a[rch].sum+=1ll*(a[rch].r-a[rch].l+1)*a[n].tag;
}
updata(n);
a[n].tag=0;
}
}
void
change(
int
n,
int
l,
int
r,
int
lc,
int
k)
{
if
(l==r && l==lc) {a[n].sum+=k;
return
;}
if
(l==r)
return
;
pushdown(n);
int
mid=(l+r)>>1;
if
(lc<=mid) change(lch,l,mid,lc,k);
else
change(rch,mid+1,r,lc,k);
updata(n);
}
void
add_tree(
int
n,
int
L,
int
R,
int
l,
int
r,
int
k)
{
if
(L==l && R==r)
{
a[n].sum+=1ll*(r-l+1)*k;
a[n].tag+=k;
return
;
}
pushdown(n);
int
mid=(L+R)>>1;
if
(r<=mid) add_tree(lch,L,mid,l,r,k);
else
if
(l>=mid+1) add_tree(rch,mid+1,R,l,r,k);
else
{
add_tree(lch,L,mid,l,mid,k);
add_tree(rch,mid+1,R,mid+1,r,k);
}
updata(n);
}
long
long
qurysum(
int
n,
int
L,
int
R,
int
l,
int
r)
{
//printf("%d %d %d %d %d\n",n,L,R,l,r);
if
(L==l && R==r)
return
a[n].sum;
pushdown(n);
int
mid=(L+R)>>1;
if
(r<=mid)
return
qurysum(lch,L,mid,l,r);
else
if
(l>=mid+1)
return
qurysum(rch,mid+1,R,l,r);
else
return
qurysum(lch,L,mid,l,mid)+qurysum(rch,mid+1,R,mid+1,r);
}
long
long
qsum(
int
x)
{
long
long
ans=0;
while
(top[x]!=1)
{
ans+=qurysum(root,1,n,line[top[x]],line[x]);
x=fa[top[x]];
}
ans+=qurysum(root,1,n,1,line[x]);
return
ans;
}
int
main()
{
scanf
(
"%d%d"
,&n,&m);
for
(
int
i=1;i<=n;i++)
scanf
(
"%lld"
,&v[i]);
for
(
int
i=1;i<n;i++)
{
int
xx,yy;
scanf
(
"%d%d"
,&xx,&yy);
add(xx,yy); add(yy,xx);
}
dfs1(1);
memset
(f,0,
sizeof
f); dfs2(1);
build_tree(root,1,n);
//for (int i=1;i<=n;i++) printf("%d ",line[i]);
//puts("");
while
(m--)
{
int
ff,xx,yy;
scanf
(
"%d"
,&ff);
if
(ff==1)
{
scanf
(
"%d%d"
,&xx,&yy);
//printf("lalal %d\n",line[xx]);
change(root,1,n,line[xx],yy);
}
else
if
(ff==2)
{
scanf
(
"%d%d"
,&xx,&yy);
//printf("laalala %d %d\n",line[xx],line[xx]+size[xx]-1);
add_tree(root,1,n,line[xx],line[xx]+size[xx]-1,yy);
}
else
if
(ff==3)
{
scanf
(
"%d"
,&xx);
printf
(
"%lld\n"
,qsum(xx));
//puts("");
}
}
return
0;
}