树链剖分裸题
/**************************************************************
Problem: 1036
User: syh0313
Language: C++
Result: Accepted
Time:2500 ms
Memory:18068 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#define lch a[n].lc
#define rch a[n].rc
using
namespace
std;
const
int
inf=1000000000;
const
int
maxe=100010;
const
int
maxd=30010;
int
nn,topt,st[maxe],to[maxe],nt[maxe],v[maxd],xx,yy,root=1,cnt,q;
int
fa[maxd],rem[maxd],size[maxd],dep[maxd];
int
dfn[maxd],line[maxd],dfn_num,top[maxd];
struct
tree
{
int
l,r,lc,rc,ma,sum;
}a[20*maxd];
bool
f[maxd];
char
s[20];
inline
void
add(
int
x,
int
y)
{to[++topt]=y; nt[topt]=st[x]; st[x]=topt;}
inline
void
dfs1(
int
x,
int
d)
{
dep[x]=d; size[x]=1; f[x]=1;
int
p=st[x];
int
ma=0;
while
(p)
{
if
(!f[to[p]])
{
fa[to[p]]=x;
dfs1(to[p],d+1);
size[x]+=size[to[p]];
if
(size[to[p]]>ma) {ma=size[to[p]]; rem[x]=to[p];}
}
p=nt[p];
}
}
inline
void
dfs2(
int
x)
{
f[x]=1;
if
(rem[fa[x]]==x) top[x]=top[fa[x]];
else
top[x]=x;
dfn[x]=++dfn_num; line[dfn_num]=x;
if
(rem[x] && !f[rem[x]]) dfs2(rem[x]);
int
p=st[x];
while
(p)
{
if
(!f[to[p]]) dfs2(to[p]);
p=nt[p];
}
}
inline
void
updata(
int
n)
{
a[n].ma=max(a[lch].ma,a[rch].ma);
a[n].sum=a[lch].sum+a[rch].sum;
}
inline
void
build_tree(
int
&n,
int
l,
int
r)
{
n=++cnt; a[n].l=l; a[n].r=r;
if
(l==r) {a[n].ma=v[line[l]]; a[n].sum=v[line[l]];
return
;}
int
mid=(l+r)>>1;
build_tree(lch,l,mid);
build_tree(rch,mid+1,r);
updata(n);
}
inline
int
qurymax(
int
n,
int
L,
int
R,
int
l,
int
r)
{
if
(L==l && R==r)
return
a[n].ma;
int
mid=(L+R)>>1;
if
(r<=mid)
return
qurymax(lch,L,mid,l,r);
else
if
(l>=mid+1)
return
qurymax(rch,mid+1,R,l,r);
else
return
max(qurymax(lch,L,mid,l,mid),qurymax(rch,mid+1,R,mid+1,r));
}
inline
int
qmax(
int
x,
int
y)
{
int
ans=-inf,l,r;
while
(top[x]!=top[y])
{
if
(dep[top[x]]<dep[top[y]]) {
int
cc=x; x=y; y=cc;}
ans=max(ans,qurymax(root,1,dfn_num,dfn[top[x]],dfn[x]));
x=fa[top[x]];
}
l=min(dfn[x],dfn[y]),r=max(dfn[x],dfn[y]);
ans=max(ans,qurymax(root,1,dfn_num,l,r));
return
ans;
}
inline
int
qurysum(
int
n,
int
L,
int
R,
int
l,
int
r)
{
if
(L==l && R==r)
return
a[n].sum;
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);
}
inline
int
qsum(
int
x,
int
y)
{
int
sum=0,l,r;
while
(top[x]!=top[y])
{
if
(dep[top[x]]<dep[top[y]]) {
int
cc=x; x=y; y=cc;}
sum+=qurysum(root,1,dfn_num,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
l=min(dfn[x],dfn[y]),r=max(dfn[x],dfn[y]);
sum+=qurysum(root,1,dfn_num,l,r);
return
sum;
}
inline
void
change(
int
n,
int
l,
int
r,
int
lc)
{
if
(l==r && r==lc) {a[n].ma=yy; a[n].sum=yy;
return
;}
if
(l==r)
return
;
int
mid=(l+r)>>1;
if
(lc<=mid) change(lch,l,mid,lc);
else
change(rch,mid+1,r,lc);
updata(n);
}
int
main()
{
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
register
int
i;
scanf
(
"%d"
,&nn);
for
(i=1;i<nn;i++)
{
scanf
(
"%d%d"
,&xx,&yy); add(xx,yy); add(yy,xx);}
fa[root]=1; dfs1(root,1);
memset
(f,0,
sizeof
f); dfs2(root);
for
(i=1;i<=nn;i++)
scanf
(
"%d"
,&v[i]);
build_tree(root,1,dfn_num);
scanf
(
"%d"
,&q);
while
(q--)
{
scanf
(
"%s %d %d"
,s,&xx,&yy);
if
(s[1]==
'M'
)
printf
(
"%d\n"
,qmax(xx,yy));
else
if
(s[1]==
'S'
)
printf
(
"%d\n"
,qsum(xx,yy));
else
if
(s[1]==
'H'
) change(root,1,dfn_num,dfn[xx]);
}
return
0;
}