树上路径


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=1e5+5;
const int iv2=(mod+1)/2;
ll w[N];
vector<int>g[N];
ll add(ll a,ll b)
{
	return (a+b)%mod; 
}

ll add(ll a,ll b,ll c)
{
	return add(add(a,b),c);
}

ll mul(ll a,ll b)
{
	return a*b%mod;
}

ll mul(ll a,ll b,ll c)
{
	return mul(mul(a,b),c);
}

int sz[N],son[N],dep[N],f[N];
void dfs(int u,int fa)
{
	dep[u]=dep[fa]+1;
	f[u]=fa;
	sz[u]=1;
	for(int v:g[u])
	{
		if(v==fa)	continue;
		dfs(v,u);
		sz[u]+=sz[v];
		if(sz[son[u]]<sz[v])
		{
			son[u]=v;
		}
	}
	
}

int idx[N],top[N],id;
ll val[N];
void DFS(int u,int tp)
{
	idx[u]=++id;
	top[u]=tp;
	val[id]=w[u];
	if(!son[u])	return;
	DFS(son[u],tp);
	for(int v:g[u])
	{
		if(!idx[v])
		{
			DFS(v,v);
		}
	}
}

struct SegTree{
	int l,r,len;
	ll lazy,sum,ans;
}Tr[N<<2];

void change(int u,ll k)
{
	Tr[u].lazy=add(Tr[u].lazy,k);
	Tr[u].ans=add(Tr[u].ans,mul(mul(Tr[u].len,iv2,Tr[u].len-1),(k*k%mod)),mul(Tr[u].sum,k,Tr[u].len-1));
	Tr[u].sum=add(Tr[u].sum,(Tr[u].len)*k%mod);
}

void pushup(int u)
{
	Tr[u].sum=add(Tr[u<<1].sum,Tr[u<<1|1].sum);
	Tr[u].ans=add(Tr[u<<1].ans,Tr[u<<1|1].ans,mul(Tr[u<<1].sum,Tr[u<<1|1].sum));
}

void pushdown(int u)
{
	if(Tr[u].lazy)
	{
		change(u<<1,Tr[u].lazy);
		change(u<<1|1,Tr[u].lazy);		
		Tr[u].lazy=0;
	}
}

void build(int u,int l,int r)
{
	Tr[u].l=l,Tr[u].r=r;
	Tr[u].len=(r-l+1);
	if(l==r)
	{
		Tr[u].sum=val[l];
		return;
	}
	int mid=(l+r)>>1;
	build(u<<1,l,mid);
	build(u<<1|1,mid+1,r);
	pushup(u);
}

void add(int u,int l,int r,ll k)
{
	//if(l>Tr[u].r||r<Tr[u].l)	return;
	if(Tr[u].l>=l&&Tr[u].r<=r)
	{
		change(u,k);
		return;
	}
	pushdown(u);
	int mid=(Tr[u].l+Tr[u].r)/2;
	if(l<=mid)	add(u<<1,l,r,k);
	if(r>mid)	add(u<<1|1,l,r,k);
	pushup(u);
}

SegTree merge(SegTree l,SegTree r)
{
	SegTree res;
	res.ans=add(l.ans,r.ans,mul(l.sum,r.sum));
	res.sum=add(l.sum,r.sum);
	return res;
}

SegTree query(int u,int l,int r)
{
	if(Tr[u].l>=l&&Tr[u].r<=r)
	{
		return Tr[u];
	}
	pushdown(u);
	int mid=(Tr[u].l+Tr[u].r)>>1;
	if(r<=mid)	return query(u<<1,l,r);
	else if(l>mid)	return query(u<<1|1,l,r);
	else return merge(query(u<<1,l,r),query(u<<1|1,l,r));
}

void Treeadd(int u,int v,ll k)
{
	while(top[u]!=top[v])
	{
		if(dep[top[u]]<dep[top[v]])	swap(u,v);
		add(1,idx[top[u]],idx[u],k);                   
		u=f[top[u]];
	}
	if(dep[v]>dep[u])	swap(u,v);
	add(1,idx[v],idx[u],k);
}

ll Treequery(int u,int v)
{
	SegTree res;
	res.sum=0,res.ans=0;
	while(top[u]!=top[v])
	{
		if(dep[top[u]]<dep[top[v]])	swap(u,v);
		res=merge(res,query(1,idx[top[u]],idx[u]));
		u=f[top[u]];
	}
	if(dep[v]>dep[u])	swap(u,v);
	res=merge(res,query(1,idx[v],idx[u]));
	return res.ans;
}

int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&w[i]);
	}
	for(int i=1;i<n;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(1,1);
	DFS(1,1);
	build(1,1,n);
	while(m--)
	{
		int opt,v,u;ll k;
		scanf("%d",&opt);
		if(opt==1)
		{
			scanf("%d%lld",&u,&k);
			add(1,idx[u],idx[u]+sz[u]-1,k);
		}   
		else if(opt==2)
		{
			scanf("%d%d%lld",&u,&v,&k);
			Treeadd(u,v,k);
		}
		else
		{
			scanf("%d%d",&u,&v);
			printf("%lld\n",Treequery(u,v));
		}    
	}
	return 0;
}

这份代码交这个题,为什么有时候段错误,有时候ac...


全部评论
咦有点神奇我看一下
点赞 回复 分享
发布于 2021-04-27 10:09
修好了,感谢报错!😃
点赞 回复 分享
发布于 2021-04-27 11:35

相关推荐

工作基本定了,比较满意。这深度学习真是难搞啊,论文看不懂,代码看不懂,不会改,创新点???&nbsp;还有一个月中期,怎么搞,已经抑郁了,没有小论文要求,我真是非常幸运了,不然就我这科研能力…………&nbsp;感觉自己对自己失去信心,无时无刻不在否定自己取得一些成绩都是运气好罢了,真的能顺利毕业吗?严重内耗、无力感爆棚啊…………
AI牛可乐:哎呀,听起来你最近压力好大呀,毕业论文和工作的双重压力一定让你感觉像是背了两座山呢。深度学习确实挺复杂的,就像是要在一片迷雾中找到出路一样。但是,你已经很棒了,工作都定好了,这是很大的成就呢! 论文的事情,别太担心。每个人都有看不懂代码和论文的时候,这是正常的。至于创新点嘛,有时候灵感就像小猫一样,需要一点一点地哄出来的。你可以先试试把你看过的资料整理一下,说不定就能找到新的思路呢。 中期答辩前,你可以列个计划,一步一步来,把大问题分解成小问题,一点一点克服。记得,你不是一个人在战斗,你的导师、同学都是你的战友哦。 至于信心嘛,别否定自己,每个人都会有低谷的时候。你已经取得的成绩,都是你实力的体现。毕业不是问题,只要你不放弃,就一定能顺利走过去的。加油哦,我相信你可以的! 对了,如果你愿意的话,可以点击我的头像,我们私信聊,也许我能帮你出出主意,或者就是简单地聊聊天,分散一下你的注意力也好呀。🐮💪🌟
点赞 评论 收藏
分享
牛客618272644号:佬携程工作怎么样,强度大吗
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务