树链剖分

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
namespace SLPF{
	#define N 100001
	int dep[N],fa[N],son[N],id[N],size[N],cost[N],top[N],_cost[N];
	int n,m,x,y,root,mod=0x7fffffff,tc,ans;
	vector<int>l[N];
	void dfs(int v,int d,int f) {
		fa[v]=f;
		dep[v]=d;
		size[v]=1;
		int Maxs=-1;
		for(int i=0; i<l[v].size(); i++) {
			int u=l[v][i];
			if(u==f)continue;
			dfs(u,d+1,v);
			size[v]+=size[u];
			if(size[u]>Maxs) {
				Maxs=size[u];
				son[v]=u;
			}
		}
	}
	void dfs2(int v,int topv) {
		id[v]=++tc;
		top[v]=topv;
		_cost[tc]=cost[v];
		if(!son[v])return ;
		dfs2(son[v],topv);
		for(int i=0; i<l[v].size(); i++) {
			int u=l[v][i];
			if(u==fa[v]||u==son[v])continue;
			dfs2(u,u);
		}
	}
	struct tree {
		#define lc now<<1
		#define rc now<<1|1
		struct node {
			int data,add,l,r;
		} a[N<<2];
		void build(int l,int r,int now) {
			a[now].l=l;
			a[now].r=r;
			if(l==r) {
				a[now].data=_cost[l];
				a[now].data%=mod;
				return ;
			}
			int mid=(l+r)>>1;
			build(l,mid,lc);
			build(mid+1,r,rc);
			a[now].data=a[lc].data+a[rc].data;
		}
		void pushdown(int now) {
			if(a[now].add) {
				a[lc].data+=a[now].add*(a[lc].r-a[lc].l+1);
				a[lc].add+=a[now].add;
				a[rc].data+=a[now].add*(a[rc].r-a[rc].l+1);
				a[rc].add+=a[now].add;
				a[now].add=0;
			}
		}
		void _Change(int l,int r,int now,int ad) {
			if(a[now].l>=l&&a[now].r<=r) {
				a[now].data+=ad*(a[now].r-a[now].l+1);
				a[now].add+=ad;
				return ;
			}
			pushdown(now);
			int mid=((a[now].l+a[now].r)>>1);
			if(l<=mid)_Change(l,r,lc,ad);
			if(r>mid) _Change(l,r,rc,ad);
			a[now].data=a[lc].data+a[rc].data;
		}
		void _Cal(int l,int r,int now) {
			if(a[now].l>=l&&a[now].r<=r) {
				ans+=a[now].data;
				return ;
			}
			pushdown(now);
			int mid=((a[now].l+a[now].r)>>1);
			if(l<=mid)_Cal(l,r,lc);
			if(r>mid)_Cal(l,r,rc);
		}
	}tr;
	void swap(int &x,int &y){
		int t=x;x=y;y=t;
	}
	int qPoint(int x,int y){
		ans=0;
		while(top[x]!=top[y]){
			if(dep[top[x]]<dep[top[y]])swap(x,y);
			tr._Cal(id[top[x]],id[x],1);
			ans%=mod;
			x=fa[top[x]];
		}
		if(dep[x]>dep[y])swap(x,y);
		tr._Cal(id[x],id[y],1);
		ans%=mod;
		return ans;
	}
	void uPoint(int x,int y,int ad){
		while(top[x]!=top[y]){
			if(dep[top[x]]<dep[top[y]])swap(x,y);
			tr._Change(id[top[x]],id[x],1,ad);
			x=fa[top[x]];
		}
		if(dep[x]>dep[y])swap(x,y);
		tr._Change(id[x],id[y],1,ad);
	}
	int qTree(int x){
		ans=0;
		tr._Cal(id[x],id[x]+size[x]-1,1);
		return ans;
	}
	void uTree(int x,int ad){
		tr._Change(id[x],id[x]+size[x]-1,1,ad);
	}
}
using namespace SLPF;
int main() {
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>cost[i];
	for(int i=1; i<n; i++) {
		cin>>x>>y;
		l[x].push_back(y);
		l[y].push_back(x);
	}
	root=1;
	dfs(root,1,-1);
	dfs2(root,root);
	tr.build(1,n,1);
	for(int i=1;i<=m;i++){
		int p,x,y,z;
		cin>>p;
		switch(p){
			case 1:{
				cin>>x>>z;
				uPoint(x,x,z);
				break;
			}
			case 2:{
				cin>>x>>y;
				uTree(x,y);
				break;
			}
			case 3:{
				cin>>x;
				cout<<qPoint(x,1)<<endl;
				break;
			}
		}
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值