Description
给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和
Input
第一行两个整数n和m,表示结点个数和操作数
接下来一行n个整数a_i,表示点i的权值 接下来n-1行,每行两个整数u,v表示存在一条(u,v)的边 接下来m行,每行一个操作,输入格式见题目描述
Output
对于每个询问输出答案
Sample Input
4 4
-4 1 5 -2
1 2
2 3
3 4
2 1 3
1 1 4 3
2 1 3
2 3 4
-4 1 5 -2
1 2
2 3
3 4
2 1 3
1 1 4 3
2 1 3
2 3 4
Sample Output
10
13
9
13
9
HINT
对于100%的数据,n,m <= 10^5 且 0<= d,|a_i|<= 10^8
因为负的数最多有n个。所以最多有n次从负数变成正数
那么我们只要维护下区间中负数的最大值。如果每次修改的时候如果加上x后变成正数了,那就暴力修改。因为最多n个负数所以复杂度最大是nlogn
然后剩下的就是直接区间加区间求和了
#include<cstdio>
using namespace std;
struct line
{
int s,t;
int next;
}a[200001];
int head[100001];
int edge;
inline void add(int s,int t)
{
a[edge].next=head[s];
head[s]=edge;
a[edge].s=s;
a[edge].t=t;
}
int son[100001],mson[100001],xson[100001],dep[100001];
int fa[100001],w[100001],px[100001],top[100001];
int tot;
int x[100001];
inline void dfs1(int d)
{
int i;
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(t!=fa[d])
{
fa[t]=d;
dfs1(t);
son[d]+=son[t]+1;
if(son[t]+1>mson[d])
{
mson[d]=son[t]+1;
xson[d]=t;
}
}
}
}
inline void dfs2(int d)
{
tot++;
w[d]=tot;
px[tot]=d;
int i;
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(t==xson[d])
{
dep[t]=dep[d]+1;
top[t]=top[d];
dfs2(t);
}
}
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(t!=xson[d]&&t!=fa[d])
{
dep[t]=dep[d]+1;
top[t]=t;
dfs2(t);
}
}
}
struct tree
{
int l,r;
long long s1,s2;
long long sx1,sx2;
long long tag;
int lo;
int m;
}tr[800001];
inline void up(int p)
{
tr[p].s1=tr[p*2].s1+tr[p*2+1].s1;
tr[p].s2=tr[p*2].s2+tr[p*2+1].s2;
tr[p].sx1=tr[p*2].sx1+tr[p*2+1].sx1;
tr[p].sx2=tr[p*2].sx2+tr[p*2+1].sx2;
if(tr[p*2].m>tr[p*2+1].m)
{
tr[p].m=tr[p*2].m;
tr[p].lo=tr[p*2].lo;
}
else
{
tr[p].m=tr[p*2+1].m;
tr[p].lo=tr[p*2+1].lo;
}
}
inline void push(int p)
{
tr[p*2].s1+=(tr[p*2].sx1*tr[p].tag);
tr[p*2+1].s1+=(tr[p*2+1].sx1*tr[p].tag);
tr[p*2].s2-=(tr[p*2].sx2*tr[p].tag);
tr[p*2+1].s2-=(tr[p*2+1].sx2*tr[p].tag);
tr[p*2].m+=tr[p].tag;
tr[p*2+1].m+=tr[p].tag;
tr[p*2].tag+=tr[p].tag;
tr[p*2+1].tag+=tr[p].tag;
tr[p].tag=0;
}
inline void build(int p,int l,int r)
{
tr[p].l=l;
tr[p].r=r;
if(l!=r)
{
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
up(p);
}
else
{
if(x[px[l]]>=0)
{
tr[p].s1=x[px[l]];
tr[p].sx1=1;
tr[p].m=-2100000000;
}
else
{
tr[p].s2=-x[px[l]];
tr[p].sx2=1;
tr[p].m=x[px[l]];
tr[p].lo=l;
}
}
}
inline tree cha(int p,int l,int r,long long x)
{
if(l<=tr[p].l&&tr[p].r<=r)
return tr[p];
else
{
push(p);
int mid=(tr[p].l+tr[p].r)/2;
bool flag1=false,flag2=false;
tree ans1,ans2,ans;
if(l<=mid)
{
flag1=true;
ans1=cha(p*2,l,r,x);
}
if(r>mid)
{
flag2=true;
ans2=cha(p*2+1,l,r,x);
}
if(flag1)
{
if(flag2)
{
if(ans1.m>ans2.m)
{
ans.m=ans1.m;
ans.lo=ans1.lo;
}
else
{
ans.m=ans2.m;
ans.lo=ans2.lo;
}
}
else
ans=ans1;
}
else
ans=ans2;
return ans;
}
}
inline void changex(int p,int l,int r)
{
if(l<=tr[p].l&&tr[p].r<=r)
{
tr[p].sx1=1;
tr[p].sx2=0;
tr[p].s1=tr[p].m;
tr[p].s2=0;
tr[p].m=-2100000000;
}
else
{
push(p);
int mid=(tr[p].l+tr[p].r)/2;
if(l<=mid)
changex(p*2,l,r);
if(r>mid)
changex(p*2+1,l,r);
up(p);
}
}
inline void add(int p,int l,int r,int x)
{
if(l<=tr[p].l&&tr[p].r<=r)
{
tr[p].tag+=x;
tr[p].s1+=(tr[p].sx1*x);
tr[p].s2-=(tr[p].sx2*x);
tr[p].m+=x;
}
else
{
push(p);
int mid=(tr[p].l+tr[p].r)/2;
if(l<=mid)
add(p*2,l,r,x);
if(r>mid)
add(p*2+1,l,r,x);
up(p);
}
}
inline long long ask(int p,int l,int r)
{
if(l<=tr[p].l&&tr[p].r<=r)
return tr[p].s1+tr[p].s2;
else
{
push(p);
int mid=(tr[p].l+tr[p].r)/2;
long long ans=0;
if(l<=mid)
ans+=ask(p*2,l,r);
if(r>mid)
ans+=ask(p*2+1,l,r);
//up(p);
return ans;
}
}
inline void change(int s,int t,long long x)
{
int u=top[s],v=top[t];
while(u!=v)
{
if(dep[u]>dep[v])
{
tree dx=cha(1,w[u],w[s],x);
while(dx.m+x>0)
{
changex(1,dx.lo,dx.lo);
dx=cha(1,w[u],w[s],x);
}
add(1,w[u],w[s],x);
s=fa[top[s]];
}
else
{
tree dx=cha(1,w[v],w[t],x);
while(dx.m+x>0)
{
changex(1,dx.lo,dx.lo);
dx=cha(1,w[v],w[t],x);
}
add(1,w[v],w[t],x);
t=fa[top[t]];
}
u=top[s];
v=top[t];
}
if(dep[s]>dep[t])
{
tree dx=cha(1,w[t],w[s],x);
while(dx.m+x>0)
{
changex(1,dx.lo,dx.lo);
dx=cha(1,w[t],w[s],x);
}
add(1,w[t],w[s],x);
}
else
{
tree dx=cha(1,w[s],w[t],x);
while(dx.m+x>0)
{
changex(1,dx.lo,dx.lo);
dx=cha(1,w[s],w[t],x);
}
add(1,w[s],w[t],x);
}
}
inline long long sum(int s,int t)
{
int u=top[s],v=top[t];
long long ans=0;
while(u!=v)
{
if(dep[u]>dep[v])
{
ans+=ask(1,w[u],w[s]);
s=fa[top[s]];
}
else
{
ans+=ask(1,w[v],w[t]);
t=fa[top[t]];
}
u=top[s];
v=top[t];
}
if(dep[s]>dep[t])
ans+=ask(1,w[t],w[s]);
else
ans+=ask(1,w[s],w[t]);
return ans;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
int i,s,t,xx;
for(i=1;i<=n;i++)
scanf("%d",&x[i]);
for(i=1;i<=n-1;i++)
{
scanf("%d%d",&s,&t);
edge++;
add(s,t);
edge++;
add(t,s);
}
dfs1(1);
dfs2(1);
build(1,1,tot);
for(i=1;i<=m;i++)
{
scanf("%d",&xx);
if(xx==1)
{
scanf("%d%d%d",&s,&t,&xx);
change(s,t,xx);
}
else
{
scanf("%d%d",&s,&t);
printf("%lld\n",sum(s,t));
}
}
return 0;
}