链剖。线段树要记录区间内负数的个数,负数的最大值..
如果增加后能使负数变正的话就往下暴力更新。。。
时间复杂度O(nlog^2n)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #define ll long long 7 using namespace std; 8 const int maxn=100233; 9 struct zs{ 10 int too,pre; 11 }e[maxn<<1];int tot1,last[maxn]; 12 int lc[maxn<<1],rc[maxn<<1],sz[maxn<<1],mx[maxn<<1],num[maxn<<1],tot; 13 ll sm[maxn<<1],add[maxn<<1],V,SM; 14 int dfn[maxn],tim,st[maxn],top,pos[maxn],bel[maxn],v[maxn],sz1[maxn],dep[maxn],fa[maxn],len[maxn],rt[maxn]; 15 int i,j,k,n,m,L,R; 16 17 int ra,fh;char rx; 18 inline int read(){ 19 rx=getchar(),ra=0,fh=1; 20 while((rx<'0'||rx>'9')&&rx!='-')rx=getchar(); 21 if(rx=='-')fh=-1,rx=getchar(); 22 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh; 23 } 24 25 26 inline void upd(int x){ 27 int l=lc[x],r=rc[x]; 28 if(mx[l]==-1e9)mx[x]=mx[r]+add[r];else 29 if(mx[r]==-1e9)mx[x]=mx[l]+add[l];else mx[x]=max(mx[l]+add[l],mx[r]+add[r]); 30 if(mx[x]>=0)mx[x]=-1e9; 31 sm[x]=sm[l]+sm[r],num[x]=num[l]+num[r]; 32 } 33 inline void pushdown(int x){ 34 int l=lc[x],r=rc[x]; 35 if(mx[l]==-1e9)sm[l]+=add[x]*sz[l]; 36 else sm[l]+=add[x]*(sz[l]-num[l]-num[l]); 37 if(mx[r]==-1e9)sm[r]+=add[x]*sz[r]; 38 else sm[r]+=add[x]*(sz[r]-num[r]-num[r]); 39 add[l]+=add[x],add[r]+=add[x], 40 add[x]=0; 41 } 42 void build(int a,int b){ 43 int x=++tot;sz[x]=b-a+1; 44 if(a==b){ 45 sm[x]=abs(v[st[a]]); 46 if(v[st[a]]<0)mx[x]=v[st[a]],num[x]=1;else mx[x]=-1e9; 47 return; 48 } 49 int mid=a+b>>1; 50 lc[x]=tot+1,build(a,mid),rc[x]=tot+1,build(mid+1,b); 51 upd(x); 52 // printf(" %d--%d sm:%lld mx:%d ",a,b,sm[x],mx[x]); 53 } 54 void insert(int x,int a,int b){ 55 if(L<=a&&R>=b){ 56 if(mx[x]==-1e9){sm[x]+=V*sz[x],add[x]+=V;return;} 57 if(mx[x]+add[x]+V<0){sm[x]+=V*(sz[x]-num[x]-num[x]),add[x]+=V;return;} 58 } 59 60 if(a==b){ 61 // printf("! %d %d ",a,mx[x]); 62 if(mx[x]+add[x]+V>=0)sm[x]=mx[x]+add[x]+V,mx[x]=-1e9,add[x]=num[x]=0; 63 else add[x]+=V,sm[x]-=V; 64 // printf(" %d %lld ",mx[x],sm[x]); 65 return; 66 } 67 if(add[x])pushdown(x); 68 int mid=a+b>>1; 69 if(L<=mid)insert(lc[x],a,mid); 70 if(R>mid)insert(rc[x],mid+1,b); 71 upd(x); 72 // printf("ins: %d--%d sm:%lld mx:%d num:%d ",a,b,sm[x],mx[x],num[x]); 73 } 74 void query(int x,int a,int b){ 75 if(L<=a&&R>=b){SM+=sm[x];/*printf("%d--%d %lld ",a,b,sm[x]);*/return;} 76 if(add[x])pushdown(x); 77 int mid=a+b>>1; 78 if(L<=mid)query(lc[x],a,mid); 79 if(R>mid)query(rc[x],mid+1,b); 80 upd(x); 81 } 82 83 void dfs(int x){ 84 sz1[x]=1,dep[x]=dep[fa[x]]+1; 85 for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]) 86 fa[e[i].too]=x,dfs(e[i].too),sz1[x]+=sz1[e[i].too]; 87 } 88 void dfs2(int x,int chain){ 89 int mx=0,i; 90 dfn[x]=++tim,pos[x]=tim-dfn[chain]+1, 91 bel[x]=chain,st[++top]=x; 92 for(i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&sz1[e[i].too]>sz1[mx])mx=e[i].too; 93 if(!mx){ 94 len[chain]=pos[x],rt[chain]=tot+1,build(1,top),top=0; 95 return; 96 }else dfs2(mx,chain); 97 for(i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&e[i].too!=mx)dfs2(e[i].too,e[i].too); 98 } 99 inline int getlca(int a,int b){ 100 if(dep[bel[a]]<dep[bel[b]])swap(a,b); 101 while(bel[a]!=bel[b]){ 102 a=fa[bel[a]]; 103 if(dep[bel[a]]<dep[bel[b]])swap(a,b); 104 } 105 return dep[a]<dep[b]?a:b; 106 } 107 108 void change(int a,int lca){ 109 while(bel[a]!=bel[lca]){ 110 L=1,R=pos[a],insert(rt[bel[a]],1,len[bel[a]]); 111 a=fa[bel[a]]; 112 } 113 if(a!=lca)L=pos[lca]+1,R=pos[a],insert(rt[bel[a]],1,len[bel[a]]); 114 } 115 void query1(int a,int lca){//printf("Q %d %d ",a,lca); 116 while(bel[a]!=bel[lca]){ 117 L=1,R=pos[a],query(rt[bel[a]],1,len[bel[a]]); 118 a=fa[bel[a]]; 119 } 120 if(a!=lca)L=pos[lca]+1,R=pos[a],/*printf("L R: %d %d ",L,R),*/query(rt[bel[a]],1,len[bel[a]]); 121 } 122 inline void insert(int a,int b){ 123 e[++tot1].too=b,e[tot1].pre=last[a],last[a]=tot1; 124 e[++tot1].too=a,e[tot1].pre=last[b],last[b]=tot1; 125 } 126 int main(){ 127 n=read(),m=read(); 128 for(i=1;i<=n;i++)v[i]=read(); 129 for(i=1;i<n;i++)insert(read(),read()); 130 dfs(1),dfs2(1,1);int id,lca,a,b; 131 // for(i=1;i<=n;i++)printf("%d bel:%d ",i,bel[i]);//return 233; 132 while(m--){ 133 id=read(),a=read(),b=read(),lca=getlca(a,b); 134 if(id==1){ 135 V=read(); 136 if(!V)continue; 137 change(a,lca),change(b,lca); 138 L=R=pos[lca],insert(rt[bel[lca]],1,len[bel[lca]]); 139 }else{ 140 SM=0; 141 query1(a,lca),query1(b,lca), 142 L=R=pos[lca],query(rt[bel[lca]],1,len[bel[lca]]); 143 printf("%lld ",SM); 144 }//puts(""); 145 } 146 return 0; 147 }