肯定是树链剖分+线段树,关键是怎么维护
绝对值和这个东西显然不能简单的合并标记
因为对于负数,加之后绝对值和是变小的
那我们考虑对负数和非负数数分别维护
下面的问题就是经过操作如果负数变成了正数怎么办
注意每次加的都是正数,这意味着这样的变化最多发生n次,
每个数发生这种变化,我们就用push到底即可,这样最多nlogn的
所以我们只要在维护一个区间最大负数即可
1 const inf=10000000000000; 2 type node=record 3 po,next:longint; 4 end; 5 link=record 6 s0,s1,mx:int64; 7 s:longint; 8 end; 9 10 var tree:array[0..100010*4] of link; 11 lazy:array[0..100010*4] of int64; 12 e:array[0..100010*2] of node; 13 top,fa,a,b,c,d,p,s:array[0..100010] of longint; 14 t,i,x,y,ch,z,len,n,m:longint; 15 16 function max(a,b:int64):int64; 17 begin 18 if a>b then exit(a) else exit(b); 19 end; 20 21 procedure swap(var a,b:longint); 22 var c:longint; 23 begin 24 c:=a; 25 a:=b; 26 b:=c; 27 end; 28 29 procedure add(x,y:longint); 30 begin 31 inc(len); 32 e[len].po:=y; 33 e[len].next:=p[x]; 34 p[x]:=len; 35 end; 36 37 procedure dfs1(x:longint); 38 var i,y:longint; 39 begin 40 i:=p[x]; 41 s[x]:=1; 42 while i<>0 do 43 begin 44 y:=e[i].po; 45 if s[y]=0 then 46 begin 47 fa[y]:=x; 48 d[y]:=d[x]+1; 49 dfs1(y); 50 s[x]:=s[x]+s[y]; 51 end; 52 i:=e[i].next; 53 end; 54 end; 55 56 procedure dfs2(x:longint); 57 var q,i,y:longint; 58 begin 59 inc(t); 60 c[x]:=t; 61 b[t]:=x; 62 i:=p[x]; 63 q:=0; 64 while i<>0 do 65 begin 66 y:=e[i].po; 67 if c[y]=0 then 68 if s[y]>s[q] then q:=y; 69 i:=e[i].next; 70 end; 71 if q<>0 then 72 begin 73 top[q]:=top[x]; 74 dfs2(q); 75 end; 76 i:=p[x]; 77 while i<>0 do 78 begin 79 y:=e[i].po; 80 if c[y]=0 then 81 begin 82 top[y]:=y; 83 dfs2(y); 84 end; 85 i:=e[i].next; 86 end; 87 end; 88 89 procedure update(i:longint); 90 begin 91 tree[i].s0:=tree[i*2].s0+tree[i*2+1].s0; 92 tree[i].s1:=tree[i*2].s1+tree[i*2+1].s1; 93 tree[i].s:=tree[i*2].s+tree[i*2+1].s; 94 tree[i].mx:=max(tree[i*2].mx,tree[i*2+1].mx); 95 end; 96 97 procedure build(i,l,r:longint); 98 var m:longint; 99 begin 100 if l=r then 101 begin 102 if a[b[l]]>=0 then 103 begin 104 tree[i].s0:=a[b[l]]; 105 tree[i].s:=1; 106 tree[i].mx:=-inf; 107 end 108 else begin 109 tree[i].s1:=a[b[l]]; 110 tree[i].mx:=a[b[l]]; 111 end; 112 end 113 else begin 114 m:=(l+r) shr 1; 115 build(i*2,l,m); 116 build(i*2+1,m+1,r); 117 update(i); 118 end; 119 end; 120 121 procedure modi(i,len:longint; z:int64); 122 begin 123 inc(lazy[i],z); 124 inc(tree[i].mx,z); 125 inc(tree[i].s0,int64(tree[i].s)*z); 126 inc(tree[i].s1,int64(len-tree[i].s)*z); 127 end; 128 129 procedure push(i,l,r:longint); 130 var m:longint; 131 begin 132 m:=(l+r) shr 1; 133 modi(i*2,m-l+1,lazy[i]); 134 modi(i*2+1,r-m,lazy[i]); 135 lazy[i]:=0; 136 end; 137 138 procedure down(i,l,r:longint); 139 var m:longint; 140 begin 141 if l=r then 142 begin 143 tree[i].s0:=tree[i].mx; 144 tree[i].s:=1; 145 tree[i].mx:=-inf; 146 tree[i].s1:=0; 147 end 148 else begin 149 m:=(l+r) shr 1; 150 if lazy[i]<>0 then push(i,l,r); 151 if tree[i*2].mx>=0 then down(i*2,l,m); 152 if tree[i*2+1].mx>=0 then down(i*2+1,m+1,r); 153 update(i); 154 end; 155 end; 156 157 procedure ins(i,l,r,x,y:longint); 158 var m:longint; 159 begin 160 if (x<=l) and (y>=r) then 161 begin 162 if tree[i].mx+z>=0 then 163 begin 164 inc(lazy[i],z); 165 inc(tree[i].mx,z); 166 down(i,l,r); 167 end 168 else modi(i,r-l+1,z); 169 end 170 else begin 171 if lazy[i]<>0 then push(i,l,r); 172 m:=(l+r) shr 1; 173 if x<=m then ins(i*2,l,m,x,y); 174 if y>m then ins(i*2+1,m+1,r,x,y); 175 update(i); 176 end; 177 end; 178 179 function get(i,l,r,x,y:longint):int64; 180 var m:longint; 181 s:int64; 182 183 begin 184 if (x<=l) and (y>=r) then exit(tree[i].s0+abs(tree[i].s1)) 185 else begin 186 if lazy[i]<>0 then push(i,l,r); 187 m:=(l+r) shr 1; 188 s:=0; 189 if x<=m then s:=s+get(i*2,l,m,x,y); 190 if y>m then s:=s+get(i*2+1,m+1,r,x,y); 191 exit(s); 192 end; 193 end; 194 195 procedure work(x,y:longint); 196 var f1,f2:longint; 197 begin 198 f1:=top[x]; 199 f2:=top[y]; 200 while f1<>f2 do 201 begin 202 if d[f1]>=d[f2] then 203 begin 204 ins(1,1,n,c[f1],c[x]); 205 x:=fa[f1]; 206 f1:=top[x]; 207 end 208 else begin 209 ins(1,1,n,c[f2],c[y]); 210 y:=fa[f2]; 211 f2:=top[y]; 212 end; 213 end; 214 if c[x]>c[y] then swap(x,y); 215 ins(1,1,n,c[x],c[y]); 216 end; 217 218 function ask(x,y:longint):int64; 219 var f1,f2:longint; 220 begin 221 ask:=0; 222 f1:=top[x]; 223 f2:=top[y]; 224 while f1<>f2 do 225 begin 226 if d[f1]>=d[f2] then 227 begin 228 ask:=ask+get(1,1,n,c[f1],c[x]); 229 x:=fa[f1]; 230 f1:=top[x]; 231 end 232 else begin 233 ask:=ask+get(1,1,n,c[f2],c[y]); 234 y:=fa[f2]; 235 f2:=top[y]; 236 end; 237 end; 238 if c[x]>c[y] then swap(x,y); 239 ask:=ask+get(1,1,n,c[x],c[y]); 240 end; 241 242 243 begin 244 readln(n,m); 245 for i:=1 to n do 246 read(a[i]); 247 for i:=1 to n-1 do 248 begin 249 readln(x,y); 250 add(x,y); 251 add(y,x); 252 end; 253 dfs1(1); 254 top[1]:=1; 255 dfs2(1); 256 build(1,1,n); 257 for i:=1 to m do 258 begin 259 read(ch,x,y); 260 if ch=1 then 261 begin 262 readln(z); 263 work(x,y); 264 end 265 else begin 266 readln; 267 writeln(ask(x,y)); 268 end; 269 end; 270 end.