For each output query, output the maximum sum in one line.
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 2e5 + 500;
const long long inf = 1LL << 45;
typedef pair<long long,long long>dl;
const long long check = -(1LL << 45);
typedef long long SgTreeDataType;
struct treenode
{
int L , R ;
SgTreeDataType sum , Lv , Rv , setv , maxv;
void updata(SgTreeDataType v)
{
setv = v ;
sum = (R-L+1)*v;
maxv = (v > 0) ? (R-L+1)*v : v;
Rv = Lv = maxv;
}
};
struct QueryData
{
long long MaxValue , Left , Right ,sum;
QueryData(long long MaxValue = 0,long long Left = 0,long long Right = 0,long long sum = 0) :MaxValue(MaxValue) , Left(Left) , Right(Right) , sum(sum){}
};
treenode tree[maxn * 4];
inline void push_down(int o)
{
if(tree[o].setv == inf) return ;
SgTreeDataType lazyval = tree[o].setv;
tree[2*o].updata(lazyval) ; tree[2*o+1].updata(lazyval);
tree[o].setv = inf;
}
inline void push_up(int o)
{
tree[o].sum = tree[2*o].sum + tree[2*o+1].sum;
tree[o].Rv = max(tree[o*2+1].Rv,tree[o*2+1].sum + tree[o*2].Rv);
tree[o].Lv = max(tree[o*2].Lv,tree[o*2].sum + tree[o*2+1].Lv);
tree[o].maxv = max( max(tree[o*2].maxv , tree[o*2+1].maxv) , max( tree[o*2].Rv + tree[o*2+1].Lv ,max(tree[o*2].sum + tree[o*2+1].Lv , tree[o*2+1].sum + tree[o*2].Rv)) );
}
inline void build_tree(int L , int R , int o)
{
tree[o].L = L , tree[o].R = R,tree[o].sum = 0 , tree[o].setv = inf , tree[o].maxv = tree[o].Lv = tree[o].Rv = 0;
if (R > L)
{
int mid = (L+R) >> 1;
build_tree(L,mid,o*2);
build_tree(mid+1,R,o*2+1);
}
}
inline void updata(int QL,int QR,SgTreeDataType v,int o)
{
int L = tree[o].L , R = tree[o].R;
if (QL <= L && R <= QR) tree[o].updata(v);
else
{
push_down(o);
int mid = (L+R)>>1;
if (QL <= mid) updata(QL,QR,v,o*2);
if (QR > mid) updata(QL,QR,v,o*2+1);
push_up(o);
}
}
inline QueryData QueryMax(int QL,int QR,int o)
{
int L = tree[o].L , R = tree[o].R;
if (QL <= L && R <= QR) return QueryData(tree[o].maxv,tree[o].Lv,tree[o].Rv,tree[o].sum);
else
{
int mid = (L+R)>>1;
push_down(o);
QueryData res;
if(QL<=mid && QR <= mid) res = QueryMax(QL,QR,2*o);
else if(QL>mid&&QR>mid) res = QueryMax(QL,QR,2*o+1);
else
{
QueryData Lv = QueryMax(QL,QR,2*o);
QueryData Rv = QueryMax(QL,QR,2*o+1);
res.MaxValue = max( max(Lv.MaxValue,Rv.MaxValue) , Lv.Right+Rv.Left );
res.Left=Lv.Left,res.Right=Rv.Right;res.sum=Lv.sum+Rv.sum;
res.Left=max(res.Left,Lv.sum+Rv.Left);
res.Right=max(res.Right,Rv.sum+Lv.Right);
}
push_up(o);
return res;
}
}
inline dl QueryLeftMax(int QL,int QR,int o)
{
int L = tree[o].L , R = tree[o].R;
if(QL<=L && R <= QR) return make_pair(tree[o].Lv,tree[o].sum);
else
{
push_down(o);
int mid = (L+R) >> 1;
dl result;
if(QL > mid) result = QueryLeftMax(QL,QR,o*2+1);
else if(QR <= mid) result = QueryLeftMax(QL,QR,o*2);
else
{
dl LL = QueryLeftMax(QL,QR,o*2);
dl RR = QueryLeftMax(QL,QR,o*2+1);
long long sum = LL.second + RR.second;
long long Lval = max(LL.first , LL.second + RR.first);
result = make_pair(Lval,sum);
}
push_up(o);
return result;
}
}
inline dl QueryRightMax(int QL,int QR,int o)
{
int L = tree[o].L , R = tree[o].R;
if(QL<=L && R <= QR) return make_pair(tree[o].Rv,tree[o].sum);
else
{
push_down(o);
int mid = (L+R) >> 1;
dl result;
if(QL > mid) result = QueryRightMax(QL,QR,o*2+1);
else if(QR <= mid) result = QueryRightMax(QL,QR,o*2);
else
{
dl LL = QueryRightMax(QL,QR,o*2);
dl RR = QueryRightMax(QL,QR,o*2+1);
long long sum = LL.second + RR.second;
long long Rval = max(RR.first , RR.second + LL.first);
result = make_pair(Rval,sum);
}
push_up(o);
return result;
}
}
long long QuerySum(int QL,int QR,int o)
{
int L = tree[o].L , R = tree[o].R;
if(QL <= L && R <= QR) return tree[o].sum;
else
{
int mid = (L+R) >> 1;
long long res = 0;
push_down(o);
if(QL <= mid) res += QuerySum(QL,QR,2*o);
if(QR > mid) res += QuerySum(QL,QR,2*o+1);
push_up(o);
return res;
}
}
vector<int>G[maxn];
int n , q ,val[maxn] , son[maxn] , idx[maxn] , top[maxn] , deep[maxn], fa[maxn] , head[maxn],T=0;
void test()
{
n = 10;
build_tree( 1 , n , 1);
for(int i = 1 ; i <= n ; ++ i) updata( i , i , i , 1);
updata(1,1,-9999,1);
QueryData res;
dl BB;
res = QueryMax(1,n,1);
BB = QueryLeftMax(1,n,1);
cout << res.MaxValue << endl;
cout << BB.first << endl;
}
//********
int dfs_clock;
int que[maxn*2],num[maxn],iii[maxn],b[maxn];
void build_List()
{
int ft = 0, rear = 0;
que[rear++] = 1;
fa[1] = 0;
deep[1] = 1;
while(ft < rear)
{
int u = que[ft++];
for(int i = 0; i < G[u].size(); i++)
{
int v = G[u][i];
if(v == fa[u]) continue;
fa[v] = u;
que[rear++] = v;
deep[v] = deep[u]+1;
}
}
memset(num, 0, sizeof (num));
for(int i = n-1; i >= 0; i--)
{
int u = que[i];
num[u]++;
num[fa[u]] += num[u];
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j < G[i].size(); j++) if(G[i][j] != fa[i])
if(G[i][0] == fa[i] || num[G[i][j]] > num[G[i][0]])
swap(G[i][0], G[i][j]);
}
top[1] = 1;
for(int i = 1; i < n; i++)
{
int u = que[i];
if(G[fa[u]][0] == u) top[u] = top[fa[u]];
else top[u] = u;
}
memset(iii, 0, sizeof (iii));
ft = 0;
dfs_clock = 0;
que[++ft] = 1;
idx[1] = ++dfs_clock;
b[1] = val[1];
while(ft)
{
int u = que[ft];
if(iii[u] >= G[u].size()) ft--;
else if(G[u][iii[u]] == fa[u]) iii[u]++;
else
{
int v = G[u][iii[u]];
que[++ft] = v;
idx[v] = ++dfs_clock;
b[idx[v]] = val[v];
iii[u]++;
}
}
for(int i = 1 ; i <= n ; ++ i) updata(i , i , b[i] , 1);
}
//*********
void my_updata(int u , int v , int c)
{
int f1 = top[u] , f2 = top[v];
while(f1 != f2)
{
if(deep[f1] < deep[f2]) swap(f1,f2) , swap(u,v);
updata(idx[top[u]],idx[u],c,1);
u = top[u] , u = fa[u] , f1 = top[u];
}
if(deep[u] > deep[v]) swap(u,v);
updata(idx[u] , idx[v] , c , 1);
}
long long solve(int u ,int v)
{
int f1 = top[u] , f2 = top[v];
if(u == v) return QueryMax(idx[u],idx[u],1).MaxValue;
long long s[2];s[0] = s[1] = check;
int cur = 0;
long long ans=check;
while(f1 != f2)
{
if(deep[f1] < deep[f2]) swap(f1,f2) , swap(u,v) , cur ^= 1;
long long sum = QuerySum(idx[top[u]],idx[u],1);
long long tt = QueryMax(idx[top[u]],idx[u],1).MaxValue;
ans = max(ans , tt);
tt = QueryRightMax(idx[top[u]],idx[u],1).first;
ans = max(ans ,tt);
ans = max(ans ,s[cur] + tt);
tt = QueryLeftMax(idx[top[u]],idx[u],1).first;
s[cur] = max(sum + s[cur],tt);
ans = max(ans , s[cur]);
u = top[u] , u = fa[u] , f1 = top[u];
}
if(deep[u] > deep[v]) swap(u,v) , cur ^= 1;
ans = max(ans , QueryMax(idx[u],idx[v],1).MaxValue);
if(s[cur^1] != (check)) ans = max( ans , s[cur^1] + QueryRightMax(idx[u],idx[v],1).first);
if(s[cur] != (check)) ans = max( ans , s[cur] + QueryLeftMax(idx[u],idx[v],1).first);
if(s[cur] != (check) && s[cur^1] != (check)) ans = max( ans , QuerySum(idx[u],idx[v],1) + s[0] + s[1]);
return ans;
}
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
return x*f;
}
int main(int argc,char * argv[])
{
scanf("%d%d",&n,&q);
for(int i = 1 ; i <= n ; ++ i) scanf("%d",val+i);
for(int i = 1 ; i < n ; ++ i)
{
int u , v;scanf("%d%d",&u,&v);
G[u].push_back(v);G[v].push_back(u);
}
build_tree(1,n,1);
build_List();
while(q--)
{
int x,y,z,w;scanf("%d%d%d%d",&x,&y,&z,&w);
if(x == 1) my_updata(y,z,w);
else printf("%lld\n",solve(y,z));
}
return 0;
}