记录编号 318112 评测结果 AAAAAAAAAA
题目名称 [HAOI 2015]树上操作 最终得分 100
用户昵称 Gravatar小e 是否通过 通过
代码语言 C++ 运行时间 1.229 s
提交时间 2016-10-08 21:03:20 内存使用 114.85 MiB
显示代码纯文本
#include "stdio.h"
#include "stdlib.h"
typedef long long LL;

const int maxnumber = 1001000;
struct Edge
{
	int to, next;
}edges[maxnumber << 1];
int head[maxnumber], tot;
int n, m;
LL value[maxnumber], num;
int depth[maxnumber], size[maxnumber], fa[maxnumber], son[maxnumber];
int dfn[maxnumber], id[maxnumber], top[maxnumber], dfsclock;
LL tree[maxnumber << 2], lazy[maxnumber << 2];

template <class T> inline void Read(T& a)
{
	a = 0;
	int minus = 1;
	char ch = getchar();
	if(ch == '-') minus = -1;
	while(ch < '0' || ch > '9'){
		ch = getchar();
		if(ch == '-') minus = -1;
	}
	while(ch >= '0' && ch <= '9'){
		a = a * 10 + ch - '0';
		ch = getchar();
	}
	a = a * minus;
}

template <class T> inline void Write(T a)
{
	int cnt = 0;
	if(a < 0){
		putchar('-');
		a = -a;
	}
	char ch[50] = {'\0'};
	while(1){
		ch[++cnt] = a % 10 + '0';
		a /= 10;
		if(!a) break;
	}
	while(cnt)
		putchar(ch[cnt--]);
	puts("");
}

template <class T> inline void Swap(T& a, T& b)
{
	T tmp = a;
	a = b;
	b = tmp;
}

inline void AddEdge(const int& from, const int& to)
{
	edges[++tot].to = to;
	edges[tot].next = head[from];
	head[from] = tot;
}

void Segment_Tree_Build(const int& l, const int& r, const int& rt)
{
	// printf("l:%d r:%d rt:%d\n", l, r, rt); while(1);
	if(l == r){
		tree[rt] = value[id[l]];
		return;
	}
	const int mid = (l + r) >> 1, lch = rt << 1, rch = lch | 1;
	Segment_Tree_Build(l, mid, lch);
	Segment_Tree_Build(mid+1, r, rch);
	tree[rt] = tree[lch] + tree[rch];
}

inline void PushDown(const int l, const int r, const int& rt)
{
	const int mid = (l + r) >> 1,lch = rt << 1, rch = lch | 1;
	lazy[lch] += lazy[rt]; lazy[rch] += lazy[rt];
	tree[lch] += (LL)(mid - l + 1) * lazy[rt];
	tree[rch] += (LL)(r - mid) * lazy[rt];
	lazy[rt] = 0;
}

void Segment_Tree_Add(const int& l, const int& r, const int& rt, const int& s, const int& t)
{
	if(s <= l && t >= r){
		tree[rt] += (r - l + 1) * num;
		lazy[rt] += num;
		return;
	}
	if(lazy[rt]) PushDown(l, r, rt);
	const int mid = (l + r) >> 1, lch = rt << 1, rch = lch | 1;
	if(t <= mid) Segment_Tree_Add(l, mid, lch, s, t);
	else if(s >= mid + 1) Segment_Tree_Add(mid+1, r, rch, s, t);
	else{
		Segment_Tree_Add(l, mid, lch, s, mid);
		Segment_Tree_Add(mid+1, r, rch, mid+1, t);
	}
	tree[rt] = tree[lch] + tree[rch];
}

LL Segment_Tree_Sum(const int& l, const int& r, const int& rt, const int& s, const int& t)
{
	if(s <= l && t >= r) return tree[rt];
	if(lazy[rt]) PushDown(l, r, rt);
	const int mid = (l + r) >> 1, lch = rt << 1, rch = lch | 1;
	if(t <= mid) return Segment_Tree_Sum(l, mid, lch, s, t);
	else if(s >= mid + 1) return Segment_Tree_Sum(mid+1, r, rch, s, t);
	return Segment_Tree_Sum(l, mid, lch, s, mid) + Segment_Tree_Sum(mid+1, r, rch, mid+1, t);
}

void DFS1(const int& a)
{
	size[a] = 1;
	for(int i = head[a]; i; i = edges[i].next){
		int to = edges[i].to;
		if(to == fa[a]) continue;
		depth[to] = depth[a] + 1;
		fa[to] = a;
		DFS1(to);
		size[a] += size[to];
		if(size[to] > size[son[a]]) son[a] = to;
	}
}

void DFS2(const int& a, const int& tp)
{
	dfn[a] = ++dfsclock;
	id[dfsclock] = a;
	top[a] = tp;
	if(son[a]) DFS2(son[a], tp);
	for(int i = head[a]; i; i = edges[i].next){
		int to = edges[i].to;
		if(to == fa[a] || to == son[a]) continue;
		DFS2(to, to);
	}
}

inline LL Query(int s, int t)
{
	LL ret = 0;
	int f1 = top[s], f2 = top[t];
	while(f1 != f2){
		if(depth[f1] < depth[f2]){
			Swap(f1, f2);
			Swap(s, t);
		}
		ret += Segment_Tree_Sum(1, n, 1, dfn[f1], dfn[s]);
		s = fa[f1];
		f1 = top[s];
	}
	if(depth[s] < depth[t]) Swap(s, t);
	ret += Segment_Tree_Sum(1, n, 1, dfn[t], dfn[s]);
	return ret;
}

#define SUBMIT
int main(int argc, char const *argv[])
{
#ifdef SUBMIT
	freopen("haoi2015_t2.in", "r", stdin); freopen("haoi2015_t2.out", "w", stdout);
#endif

	int from, to, order, s;
	Read(n); Read(m);
	for(int i = 1; i <= n; i++) Read(value[i]);
	for(int i = 1; i < n; i++){
		Read(from); Read(to);
		AddEdge(from, to);
		AddEdge(to, from);
	}

	depth[1] = 1;
	DFS1(1);
	DFS2(1, 1);
	Segment_Tree_Build(1, n, 1);

	for(int i = 1; i <= m; i++){
		Read(order);
		if(order == 1){
			Read(s); Read(num);
			Segment_Tree_Add(1, n, 1, dfn[s], dfn[s]);
		}
		else if(order == 2){
			Read(s); Read(num);
			Segment_Tree_Add(1, n, 1, dfn[s], dfn[s] + size[s] - 1);
		}
		else{
			Read(s);
			Write(Query(s, 1));
		}
	}

#ifndef SUBMIT
	printf("\n----------\n");
	getchar(); getchar();
#else
	fclose(stdin); fclose(stdout);
#endif

	return 0;
}