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
Sample Output
10
13
9
Hint
对于100%的数据,n,m <= 10^5 且 0<= d,|a_i|<= 10^8
树链剖分
我们可以在线段树里存当前的size,负数的个数,负数最大值,绝对值总和。
若添加后负数最大值仍为负,就可用懒标记,负数个数,正数个数完成操作。
加成正数也可暂时不管(反正也不用求ans),添加时随便加
询问时若当前节点负数最大值大于0了,就暴力更新所有到由负权变正的叶节点到当前点的链
权值由负变正最多n次,所以时间复杂度仍为nlogn。
#include
#define LL long long
#define O4 inline
#define inf 0x7fffffff
using namespace std;
const int N=1000005;
int n,m,a,b,c,d,e,limit;
O4 int read()
{
char t;int u=0,k=1;t=getchar();
while(t<'0'||t>'9'){if(t=='-')k=-1;t=getchar();}
while(t>='0'&&t<='9'){u=u*10+t-'0';t=getchar();}
return u*k;
}
int fa[N],deep[N],siz[N],son[N],top[N],num[N],flect[N],cnt=0,ed[N];
int nega[N*4],all[N*4],load[N],val[N*4];
LL tag[N*4],ans[N*4],maxx[N*4];
vector Map[N];
O4 void link(int a,int b)
{
Map[a].push_back(b);
Map[b].push_back(a);
}
void DFS_1(int now,int las,int D)
{
deep[now]=D;fa[now]=las;siz[now]=1;
for(int i=0;i