嗯……
因为每次加上的d都是正值,那么最多只有n次从负数到非负数的转换
所以我们分正负数分别维护,统计贡献时加一加就好了
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
const int N=100005;
const long long INF=999999999999999ll;
int n,m,dep[N],siz[N],son[N],fa[N],id[N],pre[N],segn,en,h[N],top[N];
long long a[N];
struct Edge{
int b,next;
}e[N<<1];
void AddEdge(int sa,int sb){e[++en].b=sb;e[en].next=h[sa];h[sa]=en;}
struct SegTree{
int l,r;
long long s1,s2,tag,mx,sn1,sn2,sum;
}tree[N<<2];
void Pushdown(int rt){
if(tree[rt].tag){
tree[rt<<1].tag+=tree[rt].tag;
tree[rt<<1].s1+=tree[rt<<1].sn1*tree[rt].tag;
tree[rt<<1].s2+=tree[rt<<1].sn2*tree[rt].tag;
tree[rt<<1].sum=tree[rt<<1].s1-tree[rt<<1].s2;
tree[rt<<1].mx+=tree[rt].tag;
tree[rt<<1|1].tag+=tree[rt].tag;
tree[rt<<1|1].s1+=tree[rt<<1|1].sn1*tree[rt].tag;
tree[rt<<1|1].s2+=tree[rt<<1|1].sn2*tree[rt].tag;
tree[rt<<1|1].sum=tree[rt<<1|1].s1-tree[rt<<1|1].s2;
tree[rt<<1|1].mx+=tree[rt].tag;
tree[rt].tag=0;
}
}
void Pushup(int rt){
tree[rt].mx=max(tree[rt<<1].mx,tree[rt<<1|1].mx);
tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
tree[rt].sn1=tree[rt<<1].sn1+tree[rt<<1|1].sn1;
tree[rt].sn2=tree[rt<<1].sn2+tree[rt<<1|1].sn2;
tree[rt].s1=tree[rt<<1].s1+tree[rt<<1|1].s1;
tree[rt].s2=tree[rt<<1].s2+tree[rt<<1|1].s2;
}
void Build(int rt,int l,int r){
tree[rt].l=l;tree[rt].r=r;
if(l==r){
if(a[pre[l]]>=0){
tree[rt].s1+=a[pre[l]];
tree[rt].sn1=1;
tree[rt].mx=-INF;
}
else {
tree[rt].s2+=a[pre[l]];
tree[rt].sn2=1;
tree[rt].mx=a[pre[l]];
}
tree[rt].sum=tree[rt].s1-tree[rt].s2;
return;
}
int mid=l+r>>1;
Build(rt<<1,l,mid);
Build(rt<<1|1,mid+1,r);
Pushup(rt);
}
void Ex_Modify(int rt,int d){
if(tree[rt].l==tree[rt].r){
tree[rt].sn1=1;
tree[rt].sn2=0;
tree[rt].s1=tree[rt].s2+d;
tree[rt].s2=0;
tree[rt].mx=-INF;
tree[rt].sum=tree[rt].s1;
return;
}
Pushdown(rt);
if(tree[rt<<1].mx+d>0)Ex_Modify(rt<<1,d);
else {
tree[rt<<1].tag+=d;
tree[rt<<1].s1+=tree[rt<<1].sn1*d;
tree[rt<<1].s2+=tree[rt<<1].sn2*d;
tree[rt<<1].sum=tree[rt<<1].s1-tree[rt<<1].s2;
tree[rt<<1].mx+=d;
}
if(tree[rt<<1|1].mx+d>0)Ex_Modify(rt<<1|1,d);
else {
tree[rt<<1|1].tag+=d;
tree[rt<<1|1].s1+=tree[rt<<1|1].sn1*d;
tree[rt<<1|1].s2+=tree[rt<<1|1].sn2*d;
tree[rt<<1|1].sum=tree[rt<<1|1].s1-tree[rt<<1|1].s2;
tree[rt<<1|1].mx+=d;
}
Pushup(rt);
}
void Modify(int rt,int l,int r,long long d){
if(l<=tree[rt].l && tree[rt].r<=r){
if(tree[rt].mx+d>0){Ex_Modify(rt,d);}
else {tree[rt].tag+=d;tree[rt].mx+=d;tree[rt].s1+=d*tree[rt].sn1;tree[rt].s2+=d*tree[rt].sn2;tree[rt].sum=tree[rt].s1-tree[rt].s2;}
return;
}
Pushdown(rt);
int mid=tree[rt].l+tree[rt].r>>1;
if(l<=mid)Modify(rt<<1,l,r,d);
if(r>mid)Modify(rt<<1|1,l,r,d);
Pushup(rt);
}
long long Query(int rt,int l,int r){
if(l<=tree[rt].l && tree[rt].r<=r)return tree[rt].sum;
Pushdown(rt);
int mid=tree[rt].l+tree[rt].r>>1;
if(r<=mid)return Query(rt<<1,l,r);
else if(l>mid)return Query(rt<<1|1,l,r);
else return Query(rt<<1,l,r)+Query(rt<<1|1,l,r);
}
void dfs1(int u,int fat){
dep[u]=dep[fat]+1;
fa[u]=fat;
siz[u]=1;
son[u]=0;
for(int i=h[u];i;i=e[i].next){
int v=e[i].b;
if(v==fat)continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs2(int u,int ux){
top[u]=ux;
id[u]=++segn;
pre[segn]=u;
if(son[u])dfs2(son[u],ux);
else return;
for(int i=h[u];i;i=e[i].next){
int v=e[i].b;
if(v==fa[u] || v==son[u])continue;
dfs2(v,v);
}
}
void Update(int u,int v,long long d){
int topu=top[u],topv=top[v];
while(topu!=topv){
if(dep[topu]<dep[topv]){swap(topu,topv);swap(u,v);}
Modify(1,id[topu],id[u],d);
u=fa[topu];
topu=top[u];
}
if(dep[u]>dep[v])swap(u,v);
Modify(1,id[u],id[v],d);
}
long long Ask(int u,int v){
int topu=top[u],topv=top[v];
long long Sum=0;
while(topu!=topv){
if(dep[topu]<dep[topv]){swap(topu,topv);swap(u,v);}
Sum+=Query(1,id[topu],id[u]);
u=fa[topu];
topu=top[u];
}
if(dep[u]>dep[v])swap(u,v);
return Sum+Query(1,id[u],id[v]);
}
int main(){
freopen("4127.in","r",stdin);
freopen("4127.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
for(int i=1;i<n;i++){
int u,v;
scanf("%d %d",&u,&v);
AddEdge(u,v);
AddEdge(v,u);
}
dfs1(1,0);
dfs2(1,1);
Build(1,1,n);
while(m--){
int opt,u,v;
long long d;
scanf("%d %d %d",&opt,&u,&v);
if(opt==1){scanf("%lld",&d);Update(u,v,d);}
if(opt==2)printf("%lld\n",Ask(u,v));
}
return 0;
}