记录编号 303614 评测结果 AAAAAAAAAA
题目名称 [HAOI 2015]树上操作 最终得分 100
用户昵称 Gravatar沉迷学习的假的Keller 是否通过 通过
代码语言 C++ 运行时间 3.017 s
提交时间 2016-09-06 09:05:31 内存使用 51.78 MiB
显示代码纯文本
#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#define lint long long
using namespace std;
const int maxn=500000+10;
int n,m;
lint a[maxn];
vector<int> e[maxn];

long long read(){
	long long x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-48;
		ch=getchar();
	}
	return x*f;
}
//===============================================//
// 			Heavy-Light Decomposition            //
//===============================================//
int dep[maxn],siz[maxn],fa[maxn],id[maxn],son[maxn],val[maxn],top[maxn],last[maxn],pos[maxn];
int dfs_clock;
void dfs1(int u,int d,int fath){
	dep[u]=d;
	siz[u]=1;
	son[u]=0;
	fa[u]=fath;
	for(int i=0;i<e[u].size();i++){
		int now=e[u][i];
		if(now==fath) continue;
		dfs1(now,d+1,u);
		siz[u]+=siz[now];
		if (siz[son[u]]<siz[now]){
			son[u]=now; 
		}
	}
	return ;
}

void dfs2(int u,int tp){
	top[u]=tp;
	id[u]= ++dfs_clock;
	pos[dfs_clock]=u;
	if(son[u]) dfs2(son[u],tp);
	for(int i=0;i<e[u].size();i++){
		int now=e[u][i];
		if(now!=fa[u]&&now!=son[u]){
			dfs2(now,now);	
		}
	}
	last[u]=dfs_clock;
	return ;
}

void HLD(){
	dep[1]=1;
	dfs1(1,1,0);
	dfs2(1,1);
	return ;	
}

//==============================================//
//                 Segment tree                 // 
//==============================================// 

lint sum[4*maxn],lazy[4*maxn];

void pushup(int x){
	sum[x]=sum[x*2]+sum[x*2+1];
}

void pushdown(int id,int l,int r){
	int mid=(l+r)>>1;
	lazy[id*2]+=lazy[id];sum[id*2]+=(lint)lazy[id]*(mid+1-l);
	lazy[id*2+1]+=lazy[id];sum[id*2+1]+=(lint)lazy[id]*(r-mid);
	lazy[id]=0;
	return ;
}

void build(int id,int l,int r){
	if(l==r){
		sum[id]=a[pos[l]];
		return ;
	}
	int mid=(l+r)>>1;
	build(id*2,l,mid);
	build(id*2+1,mid+1,r);
	pushup(id);
}

void add(int id,int l,int r,int x,int y,lint val){
	if(x<=l&&r<=y){
		sum[id]+=val*(r-l+1);
		lazy[id]+=val;
		return ;	
	}
	pushdown(id,l,r);
	int mid=(l+r)>>1;
	if(x<=mid){
		add(id*2,l,mid,x,y,val);	
	}
	if(y>mid){
		add(id*2+1,mid+1,r,x,y,val);	
	}
	pushup(id);
}

lint query(int id,int l,int r,int x,int y){
	if(x<=l&&r<=y){
		return sum[id];
	}
	pushdown(id,l,r);
	int mid=(l+r)>>1;
	lint ans=0;
	if(x<=mid) ans+=query(id*2,l,mid,x,y);
	if(mid<y) ans+=query(id*2+1,mid+1,r,x,y);
	return ans;
}

//================================================

lint solve(int x,int y){
	lint ans=0;
	int tp1=top[x],tp2=top[y];
	while(tp1!=tp2){
		if(dep[tp1]<dep[tp2]){
			swap(tp1,tp2);  
            swap(x,y);	
		}
		ans+=query(1,1,n,id[tp1],id[x]);  
        x=fa[tp1]; 
        tp1=top[x];
	}
	if(dep[x]>dep[y]) swap(x,y);
	ans+=query(1,1,n,id[x],id[y]);
	return ans;
}

int main(){
	freopen("haoi2015_t2.in","r",stdin);
	freopen("haoi2015_t2.out","w",stdout);
	n=read();
	m=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	for(int i=1;i<n;i++){
		lint x,y;
		x=read();
		y=read();
		e[x].push_back(y);
		e[y].push_back(x);
	}
	HLD();
	build(1,1,n);
	while(m--){
		int p,x;
		long long y;
		scanf("%d%d",&p,&x);
		if(p==1){
			y=read();
			add(1,1,n,id[x],id[x],y);
		}
		else if(p==2){
			y=read();
			add(1,1,n,id[x],last[x],y);
		}
		else if(p==3){
			printf("%lld\n",solve(1,x));
		}
	}
	return 0;
}