记录编号 272141 评测结果 AAAAAAAAAA
题目名称 [HAOI 2015]树上操作 最终得分 100
用户昵称 GravatarAntiLeaf 是否通过 通过
代码语言 C++ 运行时间 1.425 s
提交时间 2016-06-16 17:03:03 内存使用 53.72 MiB
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<iostream>
#include<fstream>
#include<algorithm>
#define lch l,mid,rt<<1
#define rch mid+1,r,rt<<1|1
using namespace std;
#define MINE
#ifdef MINE
ifstream fin("haoi2015_t2.in");
ofstream fout("haoi2015_t2.out");
#else
#define fin cin
#define fout cout
#endif
const int maxn=500010;
struct edge{
	int to;
	edge *prev;
}ee[maxn];
void insert(int,int);
void dfs1(int);
void dfs2(int,int);
void build(int,int,int);
void add(int,int,long long,int,int,int);
long long query(int,int,int,int,int);
void update(int,int,int);
long long Query(int,int);
int len=0;
edge *last[maxn];
int prt[maxn],tim=0,first[maxn],finish[maxn],top[maxn];
int depth[maxn],data[maxn],son[maxn],size[maxn],id[maxn];
long long a[maxn<<2],lazy[maxn<<2];
int n,m;
int main(){
	ios::sync_with_stdio(false);
	fin>>n>>m;
	for(int i=1;i<=n;i++)fin>>data[i];
	for(int i=1,x,y;i<n;i++){
		fin>>x>>y;
		insert(x,y);
		insert(y,x);
	}
	depth[1]=1;
	dfs1(1);
	dfs2(1,1);
	build(1,n,1);
	while(m--){
		int z,x;
		long long y;
		fin>>z>>x;
		if(z==1){
			fin>>y;
			add(first[x],first[x],y,1,n,1);
		}
		else if(z==2){
			fin>>y;
			add(first[x],finish[x],y,1,n,1);
		}
		else if(z==3){
			fout<<Query(1,x)<<'\n';
		}
	}
	return 0;
}
void insert(int x,int y){
	ee[len].to=y;
	ee[len].prev=last[x];
	last[x]=&ee[len++];
}
void dfs1(int x){
	size[x]=1;
	for(edge *e=last[x];e;e=e->prev){
		int y=e->to;
		if(y!=prt[x]){
			prt[y]=x;
			depth[y]=depth[x]+1;
			dfs1(y);
			size[x]+=size[y];
			if(size[y]>size[son[x]])son[x]=y;
		}
	}
}
void dfs2(int x,int tp){
	first[x]=++tim;
	id[tim]=x;
	top[x]=tp;
	if(son[x])dfs2(son[x],tp);
	for(edge *e=last[x];e;e=e->prev){
		int y=e->to;
		if(y^prt[x]&&y^son[x])dfs2(y,y);
	}
	finish[x]=tim;
}
void build(int l,int r,int rt){
	if(l==r){
		a[rt]=data[id[l]];
		return;
	}
	int mid=(l+r)>>1;
	build(lch);
	build(rch);
	a[rt]=a[rt<<1]+a[rt<<1|1];
}
void add(int s,int t,long long num,int l,int r,int rt){
	if(s<=l&&t>=r){
		a[rt]+=(long long)(r-l+1)*num;
		lazy[rt]+=num;
		return;
	}
	update(l,r,rt);
	int mid=(l+r)>>1;
	if(s<=mid)add(s,t,num,lch);
	if(t>mid)add(s,t,num,rch);
	a[rt]=a[rt<<1]+a[rt<<1|1];
}
long long query(int s,int t,int l,int r,int rt){
	if(s<=l&&t>=r)return a[rt];
	update(l,r,rt);
	int mid=(l+r)>>1;
	if(t<=mid)return query(s,t,l,mid,rt<<1);
	if(s>mid)return query(s,t,mid+1,r,rt<<1|1);
	return query(s,t,lch)+query(s,t,rch);
}
void update(int l,int r,int rt){
	int mid=(l+r)>>1;
	a[rt<<1]+=(long long)(mid-l+1)*lazy[rt];
	lazy[rt<<1]+=lazy[rt];
	a[rt<<1|1]+=(long long)(r-mid)*lazy[rt];
	lazy[rt<<1|1]+=lazy[rt];
	lazy[rt]=0;
}
long long Query(int x,int y){
	long long ans=0;
	int fx=top[x],fy=top[y];
	while(fx!=fy){
		if(depth[fx]<depth[fy]){
			swap(fx,fy);
			swap(x,y);
		}
		ans+=query(first[fx],first[x],1,n,1);
		x=prt[fx];
		fx=top[x];
	}
	if(depth[x]>depth[y])swap(x,y);
	ans+=query(first[x],first[y],1,n,1);
	return ans;
}