从模板题复制来打的
救救孩子,TLE 7,8!!!!
#include<cstdio>
#include<iostream>
#define int long long
using namespace std;
struct node{
int to,next;
}edge[600001];
struct node1{
int l,r,num,sum,flag,maxn;
}t[400001];
char s[101];
int maxn;
int ans;
int cntt,fa1[1000001],tot,head[1000001],cnt1,m,n,R,res,wt[1000001];
int w[10000001],id[1000001],size[1000001],depth[1000001],heavyson[1000001],top[1000001];
int inline read()
{
int x=0,f=1;
char ch;ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9' && ch>='0')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
void addedge(int u,int v)
{
edge[++cnt1].to=v;
edge[cnt1].next=head[u];
head[u]=cnt1;
}
void maketree(int tot,int l,int r)
{
t[tot].l=l;
t[tot].r=r;
if(l==r)
{
t[tot].sum=wt[l];
t[tot].maxn=wt[l];
return ;
}
int mid=(l+r)>>1;
maketree(tot<<1,l,mid);
maketree(tot<<1|1,mid+1,r);
t[tot].sum=(t[tot<<1].sum+t[tot<<1|1].sum);
t[tot].maxn=max(t[tot<<1].maxn,t[tot<<1|1].maxn);
}
void down(int tot,int l,int r) // 标记下移
{
t[tot<<1].flag+=t[tot].flag;
t[tot<<1|1].flag+=t[tot].flag;
int mid=(l+r)/2;
t[tot<<1|1].sum+=(mid-l+1)*t[tot].flag; //!!!!注意先加
t[tot<<1|1].sum+=(r-mid)*t[tot].flag;
t[tot].flag=0;
}
void change(int tot,int l,int r,int x,int y,int z) //区间更改
{
if(l>=x && r<=y)
{
t[tot].sum=(r-l+1)*z;
t[tot].maxn=z;
t[tot].flag+=z;
return ;
}
if(t[tot].flag) down(tot,l,r);
int mid=(l+r)>>1;
if(x<=mid) //在左区间
change(tot<<1,l,mid,x,y,z);
if(y>mid) // 在右区间
change(tot<<1|1,mid+1,r,x,y,z);
t[tot].sum=(t[tot<<1].sum+t[tot<<1|1].sum);
t[tot].maxn=max(t[tot<<1].maxn,t[tot<<1|1].maxn);
}
void ask(int tot,int l,int r,int x,int y)
{
if(l>=x && r<=y)
{
res+=t[tot].sum;
return ;
}
if(t[tot].flag) down(tot,l,r);
int mid=(l+r)>>1;
if(x<=mid) ask(tot<<1,l,mid,x,y);
if(y>mid) ask(tot<<1|1,mid+1,r,x,y);
}
void ask2(int tot,int l,int r,int x,int y)
{
if(l>=x && r<=y)
{
maxn=max(maxn,t[tot].maxn);
return ;
}
if(t[tot].flag) down(tot,l,r);
int mid=(l+r)/2;
if(x<=mid) ask2(tot<<1,l,mid,x,y);
if(y>mid) ask2(tot<<1|1,mid+1,r,x,y);
}
///////////////////////// 以上为线段树部分
void dfs1(int u,int fa) // 找重儿子
{
fa1[u]=fa; // 父亲节点
depth[u]=depth[fa]+1;
int heavy=0;
size[u]=1;
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if(v!=fa)
{
dfs1(v,u);
size[u]+=size[v];
if(size[u]>heavy)
{
heavyson[u]=v;
heavy=size[u];
}
}
}
}
void dfs2(int u,int k)
{
top[u]=k; // 找到链头顶端
id[u]=++cntt; // 每个节点新编号
wt[cntt]=w[u]; //把每个点的初始值赋到新编号上来
if(heavyson[u]) dfs2(heavyson[u],k); // 优先遍历重儿子
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa1[u] || v==heavyson[u]) continue;
dfs2(v,v);
}
}
void get1(int x,int y)
{
maxn=-0x7fffffff;
while(top[x]!=top[y]) // 不在同一条链上
{
if(depth[top[x]]<depth[top[y]]) swap(x,y);
ask2(1,1,n,id[top[x]],id[x]);
x=fa1[top[x]];
}
if(depth[x]>depth[y]) swap(x,y); // 在同一条链 此时x的深度比y小
ask2(1,1,n,id[x],id[y]);
printf("%lld\n",maxn);
}
void get2(int x,int y)
{
ans=0;
while(top[x]!=top[y]) // 不在同一条链上
{
if(depth[top[x]]<depth[top[y]]) swap(x,y); // 把x改为深度更深的点
res=0;
ask(1,1,n,id[top[x]],id[x]); // ans加上x点到x所在链顶端 这一段区间的点权和
ans+=res;
x=fa1[top[x]];
}
//直到两个点处于一条链上
if(depth[x]>depth[y]) swap(x,y);
res=0;
ask(1,1,n,id[x],id[y]);
ans+=res;
printf("%lld\n",ans);
}
void get3(int x,int y)
{
change(1,1,n,id[x],id[x],y);
}
signed main()
{
n=read();
for(int i=1;i<n;i++){int u,v;u=read();v=read();addedge(u,v);addedge(v,u);}
for(int i=1;i<=n;++i)
w[i]=read();
dfs1(1,0);
dfs2(1,1);
maketree(1,1,n);
m=read();
for(int i=1;i<=m;i++)
{
int k,x,y,z;
cin>>s;
if(s[0]=='C'){x=read();y=read();get3(x,y);}
if(s[0]=='Q' && s[1]=='M') {x=read();y=read();get1(x,y);}
if(s[0]=='Q' && s[1]=='S') {x=read();y=read();get2(x,y);}
}
return 0;
}