原题见洛谷
这题就是树链剖分的模板,不知道是不是国内OI水平提高太快,前几年省选题都变成模板题了...
#include<bits/stdc++.h>
using namespace std;
const int MAXN=30005;
const int INF=1000000;
int MAX[MAXN*2],sum[MAXN*2],lc[MAXN*2],rc[MAXN*2];
int fa[MAXN],dep[MAXN],size[MAXN],dfs_pos[MAXN],last[MAXN],big_son[MAXN],a[MAXN],b[MAXN],top_node[MAXN];
int N,np=0,np2=0,rt=0,dfs_clock=0;
struct edge{int to,pre;}E[MAXN*2];
char c;int flag;
void scan(int &x)
{
flag=1;
for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
if(c=='-') flag=-1,c=getchar();
for(x=0;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
x*=flag;
}
char num[20];int ct;
void print(int x)
{
ct=0;
if(x<0) putchar('-'),x=-x;
if(!x) num[ct++]='0';
while(x) num[ct++]=x%10+'0',x/=10;
while(ct--) putchar(num[ct]);
putchar('\n');
}
//---------------------------------
void addedge(int u,int v)
{
E[++np2]=(edge){v,last[u]};
last[u]=np2;
}
void DFS1(int i,int f,int d)
{
dep[i]=d; fa[i]=f; size[i]=1;
for(int p=last[i];p;p=E[p].pre)
{
int j=E[p].to;
if(j==f) continue;
DFS1(j,i,d+1); size[i]+=size[j];
if(size[j]>size[big_son[i]]) big_son[i]=j;
}
}
void DFS2(int i,int top)
{
dfs_pos[i]=++dfs_clock;
top_node[i]=top; b[dfs_clock]=a[i];
if(!big_son[i]) return;
DFS2(big_son[i],top);
for(int p=last[i];p;p=E[p].pre)
{
int j=E[p].to;
if(j==fa[i]||j==big_son[i]) continue;
DFS2(j,j);
}
}
//-------------------------------------
void pushup(int now)
{
sum[now]=sum[lc[now]]+sum[rc[now]];
MAX[now]=max(MAX[lc[now]],MAX[rc[now]]);
}
void build(int &now,int L,int R)
{
if(!now) now=++np;
if(L==R)
{
sum[now]=MAX[now]=b[L];
return;
}
int mid=(L+R)/2;
build(lc[now],L,mid);
build(rc[now],mid+1,R);
pushup(now);
}
void update(int now,int L,int R,int pos,int w)
{
if(L==pos&&R==pos)
{
sum[now]=MAX[now]=w;
return;
}
int mid=(L+R)/2;
if(pos<=mid) update(lc[now],L,mid,pos,w);
if(mid<pos) update(rc[now],mid+1,R,pos,w);
pushup(now);
}
int qmax(int now,int L,int R,int i,int j)
{
if(i<=L&&R<=j) return MAX[now];
int mid=(L+R)/2,ans=-INF;
if(i<=mid) ans=max(ans,qmax(lc[now],L,mid,i,j));
if(mid<j) ans=max(ans,qmax(rc[now],mid+1,R,i,j));
return ans;
}
int qsum(int now,int L,int R,int i,int j)
{
if(i<=L&&R<=j) return sum[now];
int mid=(L+R)/2,ans=0;
if(i<=mid) ans+=qsum(lc[now],L,mid,i,j);
if(mid<j) ans+=qsum(rc[now],mid+1,R,i,j);
return ans;
}
int MAX_range(int u,int v)
{
int ans=-INF;
while(top_node[u]!=top_node[v])
{
if(dep[top_node[u]]<dep[top_node[v]]) swap(u,v);
ans=max(ans,qmax(rt,1,N,dfs_pos[top_node[u]],dfs_pos[u]));
u=fa[top_node[u]];
}
if(dep[u]>dep[v]) swap(u,v);
return max(ans,qmax(rt,1,N,dfs_pos[u],dfs_pos[v]));
}
int SUM_range(int u,int v)
{
int ans=0;
while(top_node[u]!=top_node[v])
{
if(dep[top_node[u]]<dep[top_node[v]]) swap(u,v);
ans+=qsum(rt,1,N,dfs_pos[top_node[u]],dfs_pos[u]);
u=fa[top_node[u]];
}
if(dep[u]>dep[v]) swap(u,v);
return ans+qsum(rt,1,N,dfs_pos[u],dfs_pos[v]);
}
int main()
{
int Q,i,u,v,w;
scan(N);
for(i=1;i<N;i++)
{
scan(u);scan(v);
addedge(u,v);
addedge(v,u);
}
for(i=1;i<=N;i++) scan(a[i]);
DFS1(1,0,1); DFS2(1,1); build(rt,1,N);
scan(Q); char op[10];
while(Q--)
{
scanf("%s",op);
if(op[0]=='C')
{
scan(u);scan(w);
update(rt,1,N,dfs_pos[u],w);
}
else if(op[1]=='M')
{
scan(u);scan(v);
print(MAX_range(u,v));
}
else
{
scan(u);scan(v);
print(SUM_range(u,v));
}
}
return 0;
}