操作:
I. CHANGE u t : 把结点u的权值改为t
II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值
III. QSUM u v: 询问从点u到点v的路径上的节点的权值和
标签:树剖+线段树 模板题。
转化一下题意:
操作1:单点修改。
操作2:利用树剖求LCA的过程求经过的点的权值的最大值。
操作3:利用树剖求LCA的过程累加经过的点的权值之和。
Code:
#include<cstdio>
#include<iostream>
#include<string>
#define ri register int
using namespace std;
const int MAXN=60020;
int n,m,q,u[MAXN],v[MAXN],w[MAXN],fst[MAXN],nxt[MAXN],num,t;
int fa[MAXN],deep[MAXN],siz[MAXN],son[MAXN],cmax[MAXN],top[MAXN],dfn[MAXN],rk[MAXN],cur,a[MAXN];
int l[MAXN<<2],r[MAXN<<2],maxn[MAXN<<2],sum[MAXN<<2];
string ss;
void dfs1(int x,int father,int dep)
{
fa[x]=father,deep[x]=dep,siz[x]=1;
for(ri k=fst[x];k>0;k=nxt[k])
if(v[k]!=father)
{
dfs1(v[k],x,dep+1);
if(siz[v[k]]>cmax[x]) cmax[x]=siz[v[k]],son[x]=v[k];
siz[x]+=siz[v[k]];
}
}
void dfs2(int x,int anc)
{
top[x]=anc,dfn[x]=++cur,rk[cur]=x,a[cur]=w[x];
if(son[x]!=0) dfs2(son[x],anc);
for(ri k=fst[x];k>0;k=nxt[k])
if(v[k]!=fa[x]&&v[k]!=son[x]) dfs2(v[k],v[k]);
}
void pushup(int p)
{
sum[p]=sum[p <<1]+sum[p <<1|1];
maxn[p]=max(maxn[p <<1],maxn[p <<1|1]);
}
void build(int p,int lft,int rit)
{
l[p]=lft,r[p]=rit;
if(lft==rit) { sum[p]=a[lft]; maxn[p]=a[lft]; return; }
int mid=(lft+rit)>>1;
build(p <<1,lft,mid);
build(p <<1|1,mid+1,rit);
pushup(p);
}
void update(int p,int pla,int k)
{
if(l[p]==pla&&r[p]==pla)
{
sum[p]=k,maxn[p]=k;
return;
}
if(pla<=r[p <<1]) update(p <<1,pla,k);
if(l[p <<1|1]<=pla) update(p <<1|1,pla,k);
pushup(p);
}
int qmax(int p,int lft,int rit)
{
if(lft<=l[p]&&r[p]<=rit) return maxn[p];
int ans=-1e9;
if(lft<=r[p <<1]) ans=qmax(p <<1,lft,rit);
if(l[p <<1|1]<=rit) ans=max(ans,qmax(p <<1|1,lft,rit));
return ans;
}
int LCAmax(int x,int y)
{
int ans=-1e9;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
ans=max(ans,qmax(1,dfn[top[x]],dfn[x]));
x=fa[top[x]];
}
if(deep[x]<deep[y]) swap(x,y);
ans=max(ans,qmax(1,dfn[y],dfn[x]));
return ans;
}
int qsum(int p,int lft,int rit)
{
if(lft<=l[p]&&r[p]<=rit) return sum[p];
int ans=0;
if(lft<=r[p <<1]) ans=qsum(p <<1,lft,rit);
if(l[p <<1|1]<=rit) ans+=qsum(p <<1|1,lft,rit);
return ans;
}
int LCAsum(int x,int y)
{
int ans=0;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
ans+=qsum(1,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
if(deep[x]<deep[y]) swap(x,y);
ans+=qsum(1,dfn[y],dfn[x]);
return ans;
}
int main()
{
scanf("%d",&n);
m=(n-1)<<1;
for(ri i=1;i<=m;i+=2)
{
scanf("%d%d",&u[i],&v[i]);
nxt[i]=fst[u[i]],fst[u[i]]=i;
u[i+1]=v[i],v[i+1]=u[i];
nxt[i+1]=fst[u[i+1]],fst[u[i+1]]=i+1;
}
for(ri i=1;i<=n;i++) scanf("%d",&w[i]);
dfs1(1,1,0);
dfs2(1,1);
build(1,1,n);
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
cin>>ss>>num>>t;
if(ss=="CHANGE") update(1,dfn[num],t);
if(ss=="QMAX") cout<<LCAmax(num,t)<<'\n';
if(ss=="QSUM") cout<<LCAsum(num,t)<<'\n';
}
return 0;
}