题目大意:一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
n<=3W
裸的树链剖分。。。
这题没有区间修改所以我们可以大胆地套用ZKW线段树了(太久没写都忘光了的说)
注意修改点的时候要修改的是点的重标号而不是点本身 因为这事郁闷了一会
|点权|<=3W 3W*3W=9E 所以没必要开long long int完全能解决
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 30100
using namespace std;
struct abcd{
int to,next;
}table[M<<1];
int head[M],tot;
void add(int x,int y)
{
table[++tot].to=y;
table[tot].next=head[x];
head[x]=tot;
}
int n,m,q,Max[70000],Sum[70000],fa[M],son[M],dpt[M],top[M],pos[M],siz[M],f[M],cnt;
char s[100];
void dfs1(int x)
{
int i;
dpt[x]=dpt[fa[x]]+1;
siz[x]=1;
for(i=head[x];i;i=table[i].next)
{
if(table[i].to==fa[x])
continue;
fa[table[i].to]=x;
dfs1(table[i].to);
if(siz[table[i].to]>siz[son[x]])
son[x]=table[i].to;
siz[x]+=siz[table[i].to];
}
}
void dfs2(int x)
{
int i;
if(son[fa[x]]==x)
top[x]=top[fa[x]];
else
{
top[x]=x;
for(i=x;i;i=son[i])
pos[i]=++cnt;
}
Max[pos[x]+q]=Sum[pos[x]+q]=f[x];
for(i=head[x];i;i=table[i].next)
{
if(table[i].to==fa[x])
continue;
dfs2(table[i].to);
}
}
void Build_tree()
{
for(int i=q-1;i;i--)
Max[i]=max(Max[i<<1],Max[i<<1|1]),
Sum[i]=Sum[i<<1]+Sum[i<<1|1];
}
void change(int x,int y)
{
for(x+=q,Max[x]=Sum[x]=y,x>>=1;x;x>>=1)
Max[x]=max(Max[x<<1],Max[x<<1|1]),
Sum[x]=Sum[x<<1]+Sum[x<<1|1];
}
int getmax(int x,int y)
{
int re=0x80000000;
for(x+=q-1,y+=q+1;x^y^1;x>>=1,y>>=1)
{
if(~x&1)re=max(re,Max[x^1]);
if( y&1)re=max(re,Max[y^1]);
}
return re;
}
int Qmax(int x,int y)
{
int re=0x80000000,fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dpt[fx]<dpt[fy])
swap(x,y),swap(fx,fy);
re=max( re , getmax(pos[fx],pos[x]) );
x=fa[fx];fx=top[x];
}
if(dpt[x]<dpt[y])
swap(x,y);
re=max( re , getmax(pos[y],pos[x]) );
return re;
}
int getsum(int x,int y)
{
int re=0;
for(x+=q-1,y+=q+1;x^y^1;x>>=1,y>>=1)
{
if(~x&1)re+=Sum[x^1];
if( y&1)re+=Sum[y^1];
}
return re;
}
int Qsum(int x,int y)
{
int re=0,fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dpt[fx]<dpt[fy])
swap(x,y),swap(fx,fy);
re+=getsum(pos[fx],pos[x]);
x=fa[fx];fx=top[x];
}
if(dpt[x]<dpt[y])
swap(x,y);
re+=getsum(pos[y],pos[x]);
return re;
}
int main()
{
int i,x,y;
cin>>n;
for(q=1;q<=n+1;q<<=1);
for(i=1;i<n;i++)
scanf("%d%d",&x,&y),add(x,y),add(y,x);
for(i=1;i<=n;i++)
scanf("%d",&f[i]);
memset(Max,0xef,sizeof Max);
dfs1(1);
dfs2(1);
Build_tree();
cin>>m;
for(i=1;i<=m;i++)
{
scanf("%s%d%d",s,&x,&y);
if(s[1]=='M')
printf("%d\n", Qmax(x,y) );
else if(s[1]=='S')
printf("%d\n", Qsum(x,y) );
else
change(pos[x],y);
}
return 0;
}