【BZOJ4127】Abs

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;isiz[son[now]])son[now]=tp;
	}
}
void DFS_2(int now,int head)
{
	top[now]=head;num[now]=++cnt;flect[cnt]=now;
	if(son[now])DFS_2(son[now],head);
	for(int i=0;iqr||R>1;down(now);
	change(now*2,L,mid,ql,qr,val);
	change(now*2+1,mid+1,R,ql,qr,val);up(now);
}
O4 void build(int now,int L,int R)
{
	all[now]=R-L+1;
	if(L==R)
	{
		val[now]=load[flect[L]];
		maxx[now]=min(val[now],0);
		nega[now]=(val[now]<0);
		ans[now]=abs(val[now]);
		return;
	}
	int mid=(L+R)>>1;
	build(now*2,L,mid);build(now*2+1,mid+1,R);up(now);
}
O4 void deal(int now,int L,int R)
{
	if(L==R)
	{
		nega[now]=0;
		ans[now]=val[now];
		maxx[now]=-inf;
		return;
	}
	int mid=(L+R)>>1;down(now);
	if(maxx[now*2]>0)deal(now*2,L,mid);
	if(maxx[now*2+1]>0)deal(now*2+1,mid+1,R);up(now);
}
O4 LL ask(int now,int L,int R,int ql,int qr)
{
	if(L>qr||R0)deal(now,L,R);
	if(ql<=L&&R<=qr)return ans[now];
	int mid=(L+R)/2;down(now);
	LL tp=ask(now*2,L,mid,ql,qr)+ask(now*2+1,mid+1,R,ql,qr);
	up(now);return tp;
}
O4 LL LCA(int a,int b,int c,int d)
{
	int q1=top[a],q2=top[b];
	LL tp=0;
	while(q1!=q2)
	{
		if(deep[q1]deep[b])swap(a,b);
	if(c==233)change(1,1,n,num[a],num[b],d);
	else return tp+ask(1,1,n,num[a],num[b]);
}
int main()
{
	n=read();m=read();
	for(int i=1;i<=n;i++)load[i]=read();
	for(int i=1;i

你可能感兴趣的:(【BZOJ4127】Abs)