传送门
解析
LCT维护GSS系列操作不想解释。。。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<20|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re char c;
re bool f=0;
while(!isdigit(c=gc()))f^=c=='-';re int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return f?-num:num;
}
}
using namespace IO;
using std::cout;
using std::cerr;
inline int max(int a,int b){return a<b?b:a;}
struct node{
int lmx,rmx,mx,sum;
node(){}
node(cs int &_val){lmx=rmx=mx=max(sum=_val,0);}
friend node operator+(cs node &l,cs node &r){
node t;
t.sum=l.sum+r.sum;
t.lmx=max(l.lmx,l.sum+r.lmx);
t.rmx=max(r.rmx,r.sum+l.rmx);
t.mx=max(max(l.mx,r.mx),l.rmx+r.lmx);
return t;
}
};
cs int N=1e5+5;
std::vector<int> e[N];
inline void addedge(int u,int v){
e[u].push_back(v);
e[v].push_back(u);
}
namespace LCT{
int son[N][2],fa[N],siz[N];
node t[N];
int val[N];
bool rev[N],tag[N];
inline void pushup(int u){
siz[u]=siz[son[u][0]]+siz[son[u][1]]+1;
t[u]=t[son[u][0]]+node(val[u])+t[son[u][1]];
}
inline void pushrev(int u){
rev[u]^=1;
std::swap(son[u][0],son[u][1]);
std::swap(t[u].lmx,t[u].rmx);
}
inline void pushcover(int u,int _val){
tag[u]=1;
t[u]=node(_val*siz[u]);
val[u]=_val;
}
inline void pushdown(int u){
if(rev[u]){
if(son[u][0])pushrev(son[u][0]);
if(son[u][1])pushrev(son[u][1]);
rev[u]=0;
}
if(tag[u]){
if(son[u][0])pushcover(son[u][0],val[u]);
if(son[u][1])pushcover(son[u][1],val[u]);
tag[u]=0;
}
}
inline bool which(int u){return son[fa[u]][1]==u;}
inline bool isroot(int u){return son[fa[u]][0]!=u&&son[fa[u]][1]!=u;}
inline void Rotate(int u){
int Fa=fa[u],FA=fa[Fa];
bool pos=which(u);
if(!isroot(Fa))son[FA][which(Fa)]=u;
son[Fa][pos]=son[u][!pos];
if(son[Fa][pos])fa[son[Fa][pos]]=Fa;
son[u][!pos]=Fa;
fa[Fa]=u;fa[u]=FA;
pushup(Fa);pushup(u);
}
inline void Splay(int u){
static int q[N],qn;
q[qn=1]=u;
for(int re Fa=u;!isroot(Fa);Fa=fa[Fa])q[++qn]=fa[Fa];
while(qn)pushdown(q[qn--]);
for(int re Fa=fa[u];!isroot(u);Rotate(u),Fa=fa[u])
if(!isroot(Fa))Rotate(which(Fa)==which(u)?Fa:u);
}
inline void access(int u){
for(int re ch=0;u;u=fa[ch=u])
Splay(u),son[u][1]=ch,pushup(u);
}
inline void makeroot(int u){
access(u);Splay(u);
pushrev(u);
}
inline int query(int u,int v){
makeroot(u);
access(v);
Splay(v);
return t[v].mx;
}
inline void cover(int u,int v,int val){
makeroot(u);
access(v);
Splay(v);
pushcover(v,val);
}
}
using namespace LCT;
void dfs(int u){
for(int &v:e[u])
if(v!=fa[u])fa[v]=u,dfs(v);
}
int n;
signed main(){
n=getint();
for(int re i=1;i<=n;++i)t[i]=node(val[i]=getint());
for(int re i=1;i<n;++i)addedge(getint(),getint());
dfs(1);
n=getint();
while(n--)switch(getint()){
case 1:{
int u=getint(),v=getint();
cout<<query(u,v)<<"\n";
break;
}
case 2:{
int u=getint(),v=getint(),val=getint();
cover(u,v,val);
break;
}
}
return 0;
}