先树链剖分,开一棵线段树维护区间:1.abs的和;2.正数的数量-负数的数量;3.最大的负数。
询问就可以直接处理,考虑修改操作,对于一个区间,如果最大的负数+d变为了正数,就暴力修改下去,否则直接修改1和3两个信息并打上懒标记。因为d是非负的,所以每一个节点最多修改一次,时间复杂度不变。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 #define mid (l+r>>1) 5 #define L (k<<1) 6 #define R (L+1) 7 #define ll long long 8 struct ji{ 9 int nex,to; 10 }edge[N<<1]; 11 int E,V,n,m,p,x,y,z,w[N],head[N],fa[N],sh[N],sz[N],ma[N],top[N],id[N],id2[N],zf[N<<2],mf[N<<2]; 12 ll f[N<<2],laz[N<<2]; 13 void add(int x,int y){ 14 edge[E].nex=head[x]; 15 edge[E].to=y; 16 head[x]=E++; 17 } 18 void update(int k,ll p){ 19 mf[k]+=p; 20 f[k]+=p*zf[k]; 21 laz[k]+=p; 22 } 23 void up(int k){ 24 mf[k]=max(mf[L],mf[R])+laz[k]; 25 f[k]=f[L]+f[R]+laz[k]*zf[k]; 26 zf[k]=zf[L]+zf[R]; 27 } 28 void down(int k){ 29 update(L,laz[k]); 30 update(R,laz[k]); 31 laz[k]=0; 32 } 33 void build(int k,ll p){ 34 f[k]=abs(p); 35 zf[k]=2*(p>0)-1; 36 if (p>0)mf[k]=-0x3f3f3f3f; 37 else mf[k]=p; 38 } 39 void build(int k,int l,int r){ 40 if (l==r){ 41 build(k,w[id2[l]]); 42 return; 43 } 44 build(L,l,mid); 45 build(R,mid+1,r); 46 up(k); 47 } 48 void update(int k,int l,int r,int x,int y,int z){ 49 if ((l>y)||(x>r))return; 50 if (l==r){ 51 build(k,f[k]*zf[k]+z); 52 return; 53 } 54 if ((x<=l)&&(r<=y)&&(mf[k]+z<=0)){ 55 update(k,z); 56 return; 57 } 58 down(k); 59 update(L,l,mid,x,y,z); 60 update(R,mid+1,r,x,y,z); 61 up(k); 62 } 63 ll query(int k,int l,int r,int x,int y){ 64 if ((x>r)||(l>y))return 0; 65 if ((x<=l)&&(r<=y))return f[k]; 66 down(k); 67 return query(L,l,mid,x,y)+query(R,mid+1,r,x,y); 68 } 69 void dfs(int k,int f,int s){ 70 fa[k]=f; 71 sz[k]=1; 72 sh[k]=s; 73 for(int i=head[k];i!=-1;i=edge[i].nex) 74 if (edge[i].to!=f){ 75 dfs(edge[i].to,k,s+1); 76 sz[k]+=sz[edge[i].to]; 77 if (sz[ma[k]]<sz[edge[i].to])ma[k]=edge[i].to; 78 } 79 } 80 void dfs2(int k,int t){ 81 id[k]=++x; 82 id2[x]=k; 83 top[k]=t; 84 if (ma[k])dfs2(ma[k],t); 85 for(int i=head[k];i!=-1;i=edge[i].nex) 86 if ((edge[i].to!=fa[k])&&(edge[i].to!=ma[k]))dfs2(edge[i].to,edge[i].to); 87 } 88 ll calc(int x,int y){ 89 ll ans=0; 90 while (top[x]!=top[y]){ 91 if (sh[top[x]]<sh[top[y]])swap(x,y); 92 ans+=query(1,1,n,id[top[x]],id[x]); 93 x=fa[top[x]]; 94 } 95 if (sh[x]>sh[y])swap(x,y); 96 return ans+query(1,1,n,id[x],id[y]); 97 } 98 void update(int x,int y,int z){ 99 while (top[x]!=top[y]){ 100 if (sh[top[x]]<sh[top[y]])swap(x,y); 101 update(1,1,n,id[top[x]],id[x],z); 102 x=fa[top[x]]; 103 } 104 if (sh[x]>sh[y])swap(x,y); 105 update(1,1,n,id[x],id[y],z); 106 } 107 int main(){ 108 scanf("%d%d",&n,&m); 109 memset(head,-1,sizeof(head)); 110 for(int i=1;i<=n;i++)scanf("%d",&w[i]); 111 for(int i=1;i<n;i++){ 112 scanf("%d%d",&x,&y); 113 add(x,y); 114 add(y,x); 115 } 116 dfs(1,1,0); 117 x=0; 118 dfs2(1,1); 119 build(1,1,n); 120 for(int i=1;i<=m;i++){ 121 scanf("%d%d%d",&p,&x,&y); 122 if (p==2)printf("%lld\n",calc(x,y)); 123 else{ 124 scanf("%d",&z); 125 update(x,y,z); 126 } 127 } 128 }