White Falcon just solved the data structure problem below using heavy-light decomposition. Can you help her find a new solution that doesn't require implementing any fancy techniques? 

There are $2$ types of query operations that can be performed on a tree:

1 u x: Assign $\boldsymbol{x}$ as the value of node $\mbox{u}$.
2 u v: Print the sum of the node values in the unique path from node $\mbox{u}$ to node $\boldsymbol{\nu}$.

Given a tree with $N$ nodes where each node's value is initially $0$, execute $Q$ queries. 

Input Format

The first line contains $2$ space-separated integers, $N$ and $Q$, respectively. 

The $N-1$ subsequent lines each contain $2$ space-separated integers describing an undirected edge in the tree. 

Each of the $Q$ subsequent lines contains a query you must execute.

Constraints

$1\leq N,Q\leq10^5$
$1\leq x\leq1000$
It is guaranteed that the input describes a connected tree with $N$ nodes. 
Nodes are enumerated with $0$-based indexing.

Output Format

For each type-$2$ query, print its integer result on a new line.

Sample Input
3 3
0 1
1 2
1 0 1
1 1 2
2 0 2

Sample Output
3

Explanation

After the first $2$ queries, the value of node $n_0=1$ and the value of node $n_1=2$. The third query requires us to print the sum of the node values in the path from nodes $0$ to $2$, which is $1+2+0=3$. Thus, we print $3$ on a new line.

Difficulty: MEDIUM_HARD
Tags: Data structures
Skill types: Data structures

Starter code:

Solutions:
class heavy_light_node:

	def __init__(self, size):
		self.parent = None
		self.pos = -1
		self.weight = [0] * size
		self.fenwick = [0] * size

	def set_weight(self, i, x):
		d = x - self.weight[i]
		self.weight[i] = x
		N = len(self.weight)
		while i < N:
			self.fenwick[i] += d
			i |= i + 1

	def sum_weight(self, i):
		if i < 0:
			return 0
		x = self.fenwick[i]
		i &= i + 1
		while i:
			x += self.fenwick[i - 1]
			i &= i - 1
		return x

def build_tree(i, edges, location):
	children = []
	members = [i]
	ed = edges[i]
	while ed:
		for j in range(1, len(ed)):
			child = build_tree(ed[j], edges, location)
			child.pos = len(members) - 1
			children.append(child)
		i = ed[0]
		members.append(i)
		ed = edges[i]
	node = heavy_light_node(len(members))
	for child in children:
		child.parent = node
	for j in range(len(members)):
		location[members[j]] = (node, j)
	return node

def read_tree(N):
	edges = [[] for i in range(N)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		edges[x].append(y)
		edges[y].append(x)
	size = [0] * N
	active = [0]
	while active:
		i = active[-1]
		if size[i] == 0:
			size[i] = 1
			for j in edges[i]:
				edges[j].remove(i)
				active.append(j)
		else:
			active.pop()
			edges[i].sort(key=lambda j: -size[j])
			size[i] = 1 + sum((size[j] for j in edges[i]))
	location = [None] * N
	build_tree(0, edges, location)
	return location

def root_path(i, location):
	loc = location[i]
	path = [loc]
	loc = loc[0]
	while loc.parent != None:
		path.append((loc.parent, loc.pos))
		loc = loc.parent
	path.reverse()
	return path

def max_weight(x, y):
	px = root_path(x, location)
	py = root_path(y, location)
	m = 1
	stop = min(len(px), len(py))
	while m < stop and px[m][0] == py[m][0]:
		m += 1
	(loc, a) = px[m - 1]
	b = py[m - 1][1]
	if a > b:
		(a, b) = (b, a)
	w = loc.sum_weight(b) - loc.sum_weight(a - 1)
	for j in range(m, len(px)):
		(loc, i) = px[j]
		w += loc.sum_weight(i)
	for j in range(m, len(py)):
		(loc, i) = py[j]
		w += loc.sum_weight(i)
	return w
(N, Q) = map(int, input().split())
location = read_tree(N)
for i in range(Q):
	(t, x, y) = map(int, input().split())
	if t == 1:
		(loc, i) = location[x]
		loc.set_weight(i, y)
	elif t == 2:
		print(max_weight(x, y))


class heavy_light_node:

	def __init__(self, size):
		self.parent = None
		self.pos = -1
		self.weight = [0] * size
		self.fenwick = [0] * size

	def set_weight(self, i, x):
		d = x - self.weight[i]
		self.weight[i] = x
		N = len(self.weight)
		while i < N:
			self.fenwick[i] += d
			i |= i + 1

	def sum_weight(self, i):
		if i < 0:
			return 0
		x = self.fenwick[i]
		i &= i + 1
		while i:
			x += self.fenwick[i - 1]
			i &= i - 1
		return x

def build_tree(i, edges, location):
	children = []
	members = [i]
	ed = edges[i]
	while ed:
		for j in range(1, len(ed)):
			child = build_tree(ed[j], edges, location)
			child.pos = len(members) - 1
			children.append(child)
		i = ed[0]
		members.append(i)
		ed = edges[i]
	node = heavy_light_node(len(members))
	for child in children:
		child.parent = node
	for j in range(len(members)):
		location[members[j]] = (node, j)
	return node

def read_tree(N):
	edges = [[] for i in range(N)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		edges[x].append(y)
		edges[y].append(x)
	size = [0] * N
	active = [0]
	while active:
		i = active[-1]
		if size[i] == 0:
			size[i] = 1
			for j in edges[i]:
				edges[j].remove(i)
				active.append(j)
		else:
			active.pop()
			edges[i].sort(key=lambda j: -size[j])
			size[i] = 1 + sum((size[j] for j in edges[i]))
	location = [None] * N
	build_tree(0, edges, location)
	return location

def root_path(i, location):
	loc = location[i]
	path = [loc]
	loc = loc[0]
	while loc.parent != None:
		path.append((loc.parent, loc.pos))
		loc = loc.parent
	path.reverse()
	return path

def max_weight(x, y):
	px = root_path(x, location)
	py = root_path(y, location)
	m = 1
	stop = min(len(px), len(py))
	while m < stop and px[m][0] == py[m][0]:
		m += 1
	(loc, a) = px[m - 1]
	b = py[m - 1][1]
	if a > b:
		(a, b) = (b, a)
	w = loc.sum_weight(b) - loc.sum_weight(a - 1)
	for j in range(m, len(px)):
		(loc, i) = px[j]
		w += loc.sum_weight(i)
	for j in range(m, len(py)):
		(loc, i) = py[j]
		w += loc.sum_weight(i)
	return w
(N, Q) = map(int, input().split())
location = read_tree(N)
for i in range(Q):
	(t, x, y) = map(int, input().split())
	if t == 1:
		(loc, i) = location[x]
		loc.set_weight(i, y)
	elif t == 2:
		print(max_weight(x, y))


class heavy_light_node:

	def __init__(self, size):
		self.parent = None
		self.pos = -1
		self.weight = [0] * size
		self.fenwick = [0] * size

	def set_weight(self, i, x):
		d = x - self.weight[i]
		self.weight[i] = x
		N = len(self.weight)
		while i < N:
			self.fenwick[i] += d
			i |= i + 1

	def sum_weight(self, i):
		if i < 0:
			return 0
		x = self.fenwick[i]
		i &= i + 1
		while i:
			x += self.fenwick[i - 1]
			i &= i - 1
		return x

def build_tree(i, edges, location):
	children = []
	members = [i]
	ed = edges[i]
	while ed:
		for j in range(1, len(ed)):
			child = build_tree(ed[j], edges, location)
			child.pos = len(members) - 1
			children.append(child)
		i = ed[0]
		members.append(i)
		ed = edges[i]
	node = heavy_light_node(len(members))
	for child in children:
		child.parent = node
	for j in range(len(members)):
		location[members[j]] = (node, j)
	return node

def read_tree(N):
	edges = [[] for i in range(N)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		edges[x].append(y)
		edges[y].append(x)
	size = [0] * N
	active = [0]
	while active:
		i = active[-1]
		if size[i] == 0:
			size[i] = 1
			for j in edges[i]:
				edges[j].remove(i)
				active.append(j)
		else:
			active.pop()
			edges[i].sort(key=lambda j: -size[j])
			size[i] = 1 + sum((size[j] for j in edges[i]))
	location = [None] * N
	build_tree(0, edges, location)
	return location

def root_path(i, location):
	loc = location[i]
	path = [loc]
	loc = loc[0]
	while loc.parent != None:
		path.append((loc.parent, loc.pos))
		loc = loc.parent
	path.reverse()
	return path

def max_weight(x, y):
	px = root_path(x, location)
	py = root_path(y, location)
	m = 1
	stop = min(len(px), len(py))
	while m < stop and px[m][0] == py[m][0]:
		m += 1
	(loc, a) = px[m - 1]
	b = py[m - 1][1]
	if a > b:
		(a, b) = (b, a)
	w = loc.sum_weight(b) - loc.sum_weight(a - 1)
	for j in range(m, len(px)):
		(loc, i) = px[j]
		w += loc.sum_weight(i)
	for j in range(m, len(py)):
		(loc, i) = py[j]
		w += loc.sum_weight(i)
	return w
(N, Q) = map(int, input().split())
location = read_tree(N)
for i in range(Q):
	(t, x, y) = map(int, input().split())
	if t == 1:
		(loc, i) = location[x]
		loc.set_weight(i, y)
	elif t == 2:
		print(max_weight(x, y))


class heavy_light_node:

	def __init__(self, size):
		self.parent = None
		self.pos = -1
		self.weight = [0] * size
		self.fenwick = [0] * size

	def set_weight(self, i, x):
		d = x - self.weight[i]
		self.weight[i] = x
		N = len(self.weight)
		while i < N:
			self.fenwick[i] += d
			i |= i + 1

	def sum_weight(self, i):
		if i < 0:
			return 0
		x = self.fenwick[i]
		i &= i + 1
		while i:
			x += self.fenwick[i - 1]
			i &= i - 1
		return x

def build_tree(i, edges, location):
	children = []
	members = [i]
	ed = edges[i]
	while ed:
		for j in range(1, len(ed)):
			child = build_tree(ed[j], edges, location)
			child.pos = len(members) - 1
			children.append(child)
		i = ed[0]
		members.append(i)
		ed = edges[i]
	node = heavy_light_node(len(members))
	for child in children:
		child.parent = node
	for j in range(len(members)):
		location[members[j]] = (node, j)
	return node

def read_tree(N):
	edges = [[] for i in range(N)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		edges[x].append(y)
		edges[y].append(x)
	size = [0] * N
	active = [0]
	while active:
		i = active[-1]
		if size[i] == 0:
			size[i] = 1
			for j in edges[i]:
				edges[j].remove(i)
				active.append(j)
		else:
			active.pop()
			edges[i].sort(key=lambda j: -size[j])
			size[i] = 1 + sum((size[j] for j in edges[i]))
	location = [None] * N
	build_tree(0, edges, location)
	return location

def root_path(i, location):
	loc = location[i]
	path = [loc]
	loc = loc[0]
	while loc.parent != None:
		path.append((loc.parent, loc.pos))
		loc = loc.parent
	path.reverse()
	return path

def max_weight(x, y):
	px = root_path(x, location)
	py = root_path(y, location)
	m = 1
	stop = min(len(px), len(py))
	while m < stop and px[m][0] == py[m][0]:
		m += 1
	(loc, a) = px[m - 1]
	b = py[m - 1][1]
	if a > b:
		(a, b) = (b, a)
	w = loc.sum_weight(b) - loc.sum_weight(a - 1)
	for j in range(m, len(px)):
		(loc, i) = px[j]
		w += loc.sum_weight(i)
	for j in range(m, len(py)):
		(loc, i) = py[j]
		w += loc.sum_weight(i)
	return w
(N, Q) = map(int, input().split())
location = read_tree(N)
for i in range(Q):
	(t, x, y) = map(int, input().split())
	if t == 1:
		(loc, i) = location[x]
		loc.set_weight(i, y)
	elif t == 2:
		print(max_weight(x, y))


class heavy_light_node:

	def __init__(self, size):
		self.parent = None
		self.pos = -1
		self.weight = [0] * size
		self.fenwick = [0] * size

	def set_weight(self, i, x):
		d = x - self.weight[i]
		self.weight[i] = x
		N = len(self.weight)
		while i < N:
			self.fenwick[i] += d
			i |= i + 1

	def sum_weight(self, i):
		if i < 0:
			return 0
		x = self.fenwick[i]
		i &= i + 1
		while i:
			x += self.fenwick[i - 1]
			i &= i - 1
		return x

def build_tree(i, edges, location):
	children = []
	members = [i]
	ed = edges[i]
	while ed:
		for j in range(1, len(ed)):
			child = build_tree(ed[j], edges, location)
			child.pos = len(members) - 1
			children.append(child)
		i = ed[0]
		members.append(i)
		ed = edges[i]
	node = heavy_light_node(len(members))
	for child in children:
		child.parent = node
	for j in range(len(members)):
		location[members[j]] = (node, j)
	return node

def read_tree(N):
	edges = [[] for i in range(N)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		edges[x].append(y)
		edges[y].append(x)
	size = [0] * N
	active = [0]
	while active:
		i = active[-1]
		if size[i] == 0:
			size[i] = 1
			for j in edges[i]:
				edges[j].remove(i)
				active.append(j)
		else:
			active.pop()
			edges[i].sort(key=lambda j: -size[j])
			size[i] = 1 + sum((size[j] for j in edges[i]))
	location = [None] * N
	build_tree(0, edges, location)
	return location

def root_path(i, location):
	loc = location[i]
	path = [loc]
	loc = loc[0]
	while loc.parent != None:
		path.append((loc.parent, loc.pos))
		loc = loc.parent
	path.reverse()
	return path

def max_weight(x, y):
	px = root_path(x, location)
	py = root_path(y, location)
	m = 1
	stop = min(len(px), len(py))
	while m < stop and px[m][0] == py[m][0]:
		m += 1
	(loc, a) = px[m - 1]
	b = py[m - 1][1]
	if a > b:
		(a, b) = (b, a)
	w = loc.sum_weight(b) - loc.sum_weight(a - 1)
	for j in range(m, len(px)):
		(loc, i) = px[j]
		w += loc.sum_weight(i)
	for j in range(m, len(py)):
		(loc, i) = py[j]
		w += loc.sum_weight(i)
	return w
(N, Q) = map(int, input().split())
location = read_tree(N)
for i in range(Q):
	(t, x, y) = map(int, input().split())
	if t == 1:
		(loc, i) = location[x]
		loc.set_weight(i, y)
	elif t == 2:
		print(max_weight(x, y))


class heavy_light_node:

	def __init__(self, size):
		self.parent = None
		self.pos = -1
		self.weight = [0] * size
		self.fenwick = [0] * size

	def set_weight(self, i, x):
		d = x - self.weight[i]
		self.weight[i] = x
		N = len(self.weight)
		while i < N:
			self.fenwick[i] += d
			i |= i + 1

	def sum_weight(self, i):
		if i < 0:
			return 0
		x = self.fenwick[i]
		i &= i + 1
		while i:
			x += self.fenwick[i - 1]
			i &= i - 1
		return x

def build_tree(i, edges, location):
	children = []
	members = [i]
	ed = edges[i]
	while ed:
		for j in range(1, len(ed)):
			child = build_tree(ed[j], edges, location)
			child.pos = len(members) - 1
			children.append(child)
		i = ed[0]
		members.append(i)
		ed = edges[i]
	node = heavy_light_node(len(members))
	for child in children:
		child.parent = node
	for j in range(len(members)):
		location[members[j]] = (node, j)
	return node

def read_tree(N):
	edges = [[] for i in range(N)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		edges[x].append(y)
		edges[y].append(x)
	size = [0] * N
	active = [0]
	while active:
		i = active[-1]
		if size[i] == 0:
			size[i] = 1
			for j in edges[i]:
				edges[j].remove(i)
				active.append(j)
		else:
			active.pop()
			edges[i].sort(key=lambda j: -size[j])
			size[i] = 1 + sum((size[j] for j in edges[i]))
	location = [None] * N
	build_tree(0, edges, location)
	return location

def root_path(i, location):
	loc = location[i]
	path = [loc]
	loc = loc[0]
	while loc.parent != None:
		path.append((loc.parent, loc.pos))
		loc = loc.parent
	path.reverse()
	return path

def max_weight(x, y):
	px = root_path(x, location)
	py = root_path(y, location)
	m = 1
	stop = min(len(px), len(py))
	while m < stop and px[m][0] == py[m][0]:
		m += 1
	(loc, a) = px[m - 1]
	b = py[m - 1][1]
	if a > b:
		(a, b) = (b, a)
	w = loc.sum_weight(b) - loc.sum_weight(a - 1)
	for j in range(m, len(px)):
		(loc, i) = px[j]
		w += loc.sum_weight(i)
	for j in range(m, len(py)):
		(loc, i) = py[j]
		w += loc.sum_weight(i)
	return w
(N, Q) = map(int, input().split())
location = read_tree(N)
for i in range(Q):
	(t, x, y) = map(int, input().split())
	if t == 1:
		(loc, i) = location[x]
		loc.set_weight(i, y)
	elif t == 2:
		print(max_weight(x, y))


class heavy_light_node:

	def __init__(self, size):
		self.parent = None
		self.pos = -1
		self.weight = [0] * size
		self.fenwick = [0] * size

	def set_weight(self, i, x):
		d = x - self.weight[i]
		self.weight[i] = x
		N = len(self.weight)
		while i < N:
			self.fenwick[i] += d
			i |= i + 1

	def sum_weight(self, i):
		if i < 0:
			return 0
		x = self.fenwick[i]
		i &= i + 1
		while i:
			x += self.fenwick[i - 1]
			i &= i - 1
		return x

def build_tree(i, edges, location):
	children = []
	members = [i]
	ed = edges[i]
	while ed:
		for j in range(1, len(ed)):
			child = build_tree(ed[j], edges, location)
			child.pos = len(members) - 1
			children.append(child)
		i = ed[0]
		members.append(i)
		ed = edges[i]
	node = heavy_light_node(len(members))
	for child in children:
		child.parent = node
	for j in range(len(members)):
		location[members[j]] = (node, j)
	return node

def read_tree(N):
	edges = [[] for i in range(N)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		edges[x].append(y)
		edges[y].append(x)
	size = [0] * N
	active = [0]
	while active:
		i = active[-1]
		if size[i] == 0:
			size[i] = 1
			for j in edges[i]:
				edges[j].remove(i)
				active.append(j)
		else:
			active.pop()
			edges[i].sort(key=lambda j: -size[j])
			size[i] = 1 + sum((size[j] for j in edges[i]))
	location = [None] * N
	build_tree(0, edges, location)
	return location

def root_path(i, location):
	loc = location[i]
	path = [loc]
	loc = loc[0]
	while loc.parent != None:
		path.append((loc.parent, loc.pos))
		loc = loc.parent
	path.reverse()
	return path

def max_weight(x, y):
	px = root_path(x, location)
	py = root_path(y, location)
	m = 1
	stop = min(len(px), len(py))
	while m < stop and px[m][0] == py[m][0]:
		m += 1
	(loc, a) = px[m - 1]
	b = py[m - 1][1]
	if a > b:
		(a, b) = (b, a)
	w = loc.sum_weight(b) - loc.sum_weight(a - 1)
	for j in range(m, len(px)):
		(loc, i) = px[j]
		w += loc.sum_weight(i)
	for j in range(m, len(py)):
		(loc, i) = py[j]
		w += loc.sum_weight(i)
	return w
(N, Q) = map(int, input().split())
location = read_tree(N)
for i in range(Q):
	(t, x, y) = map(int, input().split())
	if t == 1:
		(loc, i) = location[x]
		loc.set_weight(i, y)
	elif t == 2:
		print(max_weight(x, y))


class heavy_light_node:

	def __init__(self, size):
		self.parent = None
		self.pos = -1
		self.weight = [0] * size
		self.fenwick = [0] * size

	def set_weight(self, i, x):
		d = x - self.weight[i]
		self.weight[i] = x
		N = len(self.weight)
		while i < N:
			self.fenwick[i] += d
			i |= i + 1

	def sum_weight(self, i):
		if i < 0:
			return 0
		x = self.fenwick[i]
		i &= i + 1
		while i:
			x += self.fenwick[i - 1]
			i &= i - 1
		return x

def build_tree(i, edges, location):
	children = []
	members = [i]
	ed = edges[i]
	while ed:
		for j in range(1, len(ed)):
			child = build_tree(ed[j], edges, location)
			child.pos = len(members) - 1
			children.append(child)
		i = ed[0]
		members.append(i)
		ed = edges[i]
	node = heavy_light_node(len(members))
	for child in children:
		child.parent = node
	for j in range(len(members)):
		location[members[j]] = (node, j)
	return node

def read_tree(N):
	edges = [[] for i in range(N)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		edges[x].append(y)
		edges[y].append(x)
	size = [0] * N
	active = [0]
	while active:
		i = active[-1]
		if size[i] == 0:
			size[i] = 1
			for j in edges[i]:
				edges[j].remove(i)
				active.append(j)
		else:
			active.pop()
			edges[i].sort(key=lambda j: -size[j])
			size[i] = 1 + sum((size[j] for j in edges[i]))
	location = [None] * N
	build_tree(0, edges, location)
	return location

def root_path(i, location):
	loc = location[i]
	path = [loc]
	loc = loc[0]
	while loc.parent != None:
		path.append((loc.parent, loc.pos))
		loc = loc.parent
	path.reverse()
	return path

def max_weight(x, y):
	px = root_path(x, location)
	py = root_path(y, location)
	m = 1
	stop = min(len(px), len(py))
	while m < stop and px[m][0] == py[m][0]:
		m += 1
	(loc, a) = px[m - 1]
	b = py[m - 1][1]
	if a > b:
		(a, b) = (b, a)
	w = loc.sum_weight(b) - loc.sum_weight(a - 1)
	for j in range(m, len(px)):
		(loc, i) = px[j]
		w += loc.sum_weight(i)
	for j in range(m, len(py)):
		(loc, i) = py[j]
		w += loc.sum_weight(i)
	return w
(N, Q) = map(int, input().split())
location = read_tree(N)
for i in range(Q):
	(t, x, y) = map(int, input().split())
	if t == 1:
		(loc, i) = location[x]
		loc.set_weight(i, y)
	elif t == 2:
		print(max_weight(x, y))


class heavy_light_node:

	def __init__(self, size):
		self.parent = None
		self.pos = -1
		self.weight = [0] * size
		self.fenwick = [0] * size

	def set_weight(self, i, x):
		d = x - self.weight[i]
		self.weight[i] = x
		N = len(self.weight)
		while i < N:
			self.fenwick[i] += d
			i |= i + 1

	def sum_weight(self, i):
		if i < 0:
			return 0
		x = self.fenwick[i]
		i &= i + 1
		while i:
			x += self.fenwick[i - 1]
			i &= i - 1
		return x

def build_tree(i, edges, location):
	children = []
	members = [i]
	ed = edges[i]
	while ed:
		for j in range(1, len(ed)):
			child = build_tree(ed[j], edges, location)
			child.pos = len(members) - 1
			children.append(child)
		i = ed[0]
		members.append(i)
		ed = edges[i]
	node = heavy_light_node(len(members))
	for child in children:
		child.parent = node
	for j in range(len(members)):
		location[members[j]] = (node, j)
	return node

def read_tree(N):
	edges = [[] for i in range(N)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		edges[x].append(y)
		edges[y].append(x)
	size = [0] * N
	active = [0]
	while active:
		i = active[-1]
		if size[i] == 0:
			size[i] = 1
			for j in edges[i]:
				edges[j].remove(i)
				active.append(j)
		else:
			active.pop()
			edges[i].sort(key=lambda j: -size[j])
			size[i] = 1 + sum((size[j] for j in edges[i]))
	location = [None] * N
	build_tree(0, edges, location)
	return location

def root_path(i, location):
	loc = location[i]
	path = [loc]
	loc = loc[0]
	while loc.parent != None:
		path.append((loc.parent, loc.pos))
		loc = loc.parent
	path.reverse()
	return path

def max_weight(x, y):
	px = root_path(x, location)
	py = root_path(y, location)
	m = 1
	stop = min(len(px), len(py))
	while m < stop and px[m][0] == py[m][0]:
		m += 1
	(loc, a) = px[m - 1]
	b = py[m - 1][1]
	if a > b:
		(a, b) = (b, a)
	w = loc.sum_weight(b) - loc.sum_weight(a - 1)
	for j in range(m, len(px)):
		(loc, i) = px[j]
		w += loc.sum_weight(i)
	for j in range(m, len(py)):
		(loc, i) = py[j]
		w += loc.sum_weight(i)
	return w
(N, Q) = map(int, input().split())
location = read_tree(N)
for i in range(Q):
	(t, x, y) = map(int, input().split())
	if t == 1:
		(loc, i) = location[x]
		loc.set_weight(i, y)
	elif t == 2:
		print(max_weight(x, y))


class heavy_light_node:

	def __init__(self, size):
		self.parent = None
		self.pos = -1
		self.weight = [0] * size
		self.fenwick = [0] * size

	def set_weight(self, i, x):
		d = x - self.weight[i]
		self.weight[i] = x
		N = len(self.weight)
		while i < N:
			self.fenwick[i] += d
			i |= i + 1

	def sum_weight(self, i):
		if i < 0:
			return 0
		x = self.fenwick[i]
		i &= i + 1
		while i:
			x += self.fenwick[i - 1]
			i &= i - 1
		return x

def build_tree(i, edges, location):
	children = []
	members = [i]
	ed = edges[i]
	while ed:
		for j in range(1, len(ed)):
			child = build_tree(ed[j], edges, location)
			child.pos = len(members) - 1
			children.append(child)
		i = ed[0]
		members.append(i)
		ed = edges[i]
	node = heavy_light_node(len(members))
	for child in children:
		child.parent = node
	for j in range(len(members)):
		location[members[j]] = (node, j)
	return node

def read_tree(N):
	edges = [[] for i in range(N)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		edges[x].append(y)
		edges[y].append(x)
	size = [0] * N
	active = [0]
	while active:
		i = active[-1]
		if size[i] == 0:
			size[i] = 1
			for j in edges[i]:
				edges[j].remove(i)
				active.append(j)
		else:
			active.pop()
			edges[i].sort(key=lambda j: -size[j])
			size[i] = 1 + sum((size[j] for j in edges[i]))
	location = [None] * N
	build_tree(0, edges, location)
	return location

def root_path(i, location):
	loc = location[i]
	path = [loc]
	loc = loc[0]
	while loc.parent != None:
		path.append((loc.parent, loc.pos))
		loc = loc.parent
	path.reverse()
	return path

def max_weight(x, y):
	px = root_path(x, location)
	py = root_path(y, location)
	m = 1
	stop = min(len(px), len(py))
	while m < stop and px[m][0] == py[m][0]:
		m += 1
	(loc, a) = px[m - 1]
	b = py[m - 1][1]
	if a > b:
		(a, b) = (b, a)
	w = loc.sum_weight(b) - loc.sum_weight(a - 1)
	for j in range(m, len(px)):
		(loc, i) = px[j]
		w += loc.sum_weight(i)
	for j in range(m, len(py)):
		(loc, i) = py[j]
		w += loc.sum_weight(i)
	return w
(N, Q) = map(int, input().split())
location = read_tree(N)
for i in range(Q):
	(t, x, y) = map(int, input().split())
	if t == 1:
		(loc, i) = location[x]
		loc.set_weight(i, y)
	elif t == 2:
		print(max_weight(x, y))


class heavy_light_node:

	def __init__(self, size):
		self.parent = None
		self.pos = -1
		self.weight = [0] * size
		self.fenwick = [0] * size

	def set_weight(self, i, x):
		d = x - self.weight[i]
		self.weight[i] = x
		N = len(self.weight)
		while i < N:
			self.fenwick[i] += d
			i |= i + 1

	def sum_weight(self, i):
		if i < 0:
			return 0
		x = self.fenwick[i]
		i &= i + 1
		while i:
			x += self.fenwick[i - 1]
			i &= i - 1
		return x

def build_tree(i, edges, location):
	children = []
	members = [i]
	ed = edges[i]
	while ed:
		for j in range(1, len(ed)):
			child = build_tree(ed[j], edges, location)
			child.pos = len(members) - 1
			children.append(child)
		i = ed[0]
		members.append(i)
		ed = edges[i]
	node = heavy_light_node(len(members))
	for child in children:
		child.parent = node
	for j in range(len(members)):
		location[members[j]] = (node, j)
	return node

def read_tree(N):
	edges = [[] for i in range(N)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		edges[x].append(y)
		edges[y].append(x)
	size = [0] * N
	active = [0]
	while active:
		i = active[-1]
		if size[i] == 0:
			size[i] = 1
			for j in edges[i]:
				edges[j].remove(i)
				active.append(j)
		else:
			active.pop()
			edges[i].sort(key=lambda j: -size[j])
			size[i] = 1 + sum((size[j] for j in edges[i]))
	location = [None] * N
	build_tree(0, edges, location)
	return location

def root_path(i, location):
	loc = location[i]
	path = [loc]
	loc = loc[0]
	while loc.parent != None:
		path.append((loc.parent, loc.pos))
		loc = loc.parent
	path.reverse()
	return path

def max_weight(x, y):
	px = root_path(x, location)
	py = root_path(y, location)
	m = 1
	stop = min(len(px), len(py))
	while m < stop and px[m][0] == py[m][0]:
		m += 1
	(loc, a) = px[m - 1]
	b = py[m - 1][1]
	if a > b:
		(a, b) = (b, a)
	w = loc.sum_weight(b) - loc.sum_weight(a - 1)
	for j in range(m, len(px)):
		(loc, i) = px[j]
		w += loc.sum_weight(i)
	for j in range(m, len(py)):
		(loc, i) = py[j]
		w += loc.sum_weight(i)
	return w
(N, Q) = map(int, input().split())
location = read_tree(N)
for i in range(Q):
	(t, x, y) = map(int, input().split())
	if t == 1:
		(loc, i) = location[x]
		loc.set_weight(i, y)
	elif t == 2:
		print(max_weight(x, y))


class heavy_light_node:

	def __init__(self, size):
		self.parent = None
		self.pos = -1
		self.weight = [0] * size
		self.fenwick = [0] * size

	def set_weight(self, i, x):
		d = x - self.weight[i]
		self.weight[i] = x
		N = len(self.weight)
		while i < N:
			self.fenwick[i] += d
			i |= i + 1

	def sum_weight(self, i):
		if i < 0:
			return 0
		x = self.fenwick[i]
		i &= i + 1
		while i:
			x += self.fenwick[i - 1]
			i &= i - 1
		return x

def build_tree(i, edges, location):
	children = []
	members = [i]
	ed = edges[i]
	while ed:
		for j in range(1, len(ed)):
			child = build_tree(ed[j], edges, location)
			child.pos = len(members) - 1
			children.append(child)
		i = ed[0]
		members.append(i)
		ed = edges[i]
	node = heavy_light_node(len(members))
	for child in children:
		child.parent = node
	for j in range(len(members)):
		location[members[j]] = (node, j)
	return node

def read_tree(N):
	edges = [[] for i in range(N)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		edges[x].append(y)
		edges[y].append(x)
	size = [0] * N
	active = [0]
	while active:
		i = active[-1]
		if size[i] == 0:
			size[i] = 1
			for j in edges[i]:
				edges[j].remove(i)
				active.append(j)
		else:
			active.pop()
			edges[i].sort(key=lambda j: -size[j])
			size[i] = 1 + sum((size[j] for j in edges[i]))
	location = [None] * N
	build_tree(0, edges, location)
	return location

def root_path(i, location):
	loc = location[i]
	path = [loc]
	loc = loc[0]
	while loc.parent != None:
		path.append((loc.parent, loc.pos))
		loc = loc.parent
	path.reverse()
	return path

def max_weight(x, y):
	px = root_path(x, location)
	py = root_path(y, location)
	m = 1
	stop = min(len(px), len(py))
	while m < stop and px[m][0] == py[m][0]:
		m += 1
	(loc, a) = px[m - 1]
	b = py[m - 1][1]
	if a > b:
		(a, b) = (b, a)
	w = loc.sum_weight(b) - loc.sum_weight(a - 1)
	for j in range(m, len(px)):
		(loc, i) = px[j]
		w += loc.sum_weight(i)
	for j in range(m, len(py)):
		(loc, i) = py[j]
		w += loc.sum_weight(i)
	return w
(N, Q) = map(int, input().split())
location = read_tree(N)
for i in range(Q):
	(t, x, y) = map(int, input().split())
	if t == 1:
		(loc, i) = location[x]
		loc.set_weight(i, y)
	elif t == 2:
		print(max_weight(x, y))


class heavy_light_node:

	def __init__(self, size):
		self.parent = None
		self.pos = -1
		self.weight = [0] * size
		self.fenwick = [0] * size

	def set_weight(self, i, x):
		d = x - self.weight[i]
		self.weight[i] = x
		N = len(self.weight)
		while i < N:
			self.fenwick[i] += d
			i |= i + 1

	def sum_weight(self, i):
		if i < 0:
			return 0
		x = self.fenwick[i]
		i &= i + 1
		while i:
			x += self.fenwick[i - 1]
			i &= i - 1
		return x

def build_tree(i, edges, location):
	children = []
	members = [i]
	ed = edges[i]
	while ed:
		for j in range(1, len(ed)):
			child = build_tree(ed[j], edges, location)
			child.pos = len(members) - 1
			children.append(child)
		i = ed[0]
		members.append(i)
		ed = edges[i]
	node = heavy_light_node(len(members))
	for child in children:
		child.parent = node
	for j in range(len(members)):
		location[members[j]] = (node, j)
	return node

def read_tree(N):
	edges = [[] for i in range(N)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		edges[x].append(y)
		edges[y].append(x)
	size = [0] * N
	active = [0]
	while active:
		i = active[-1]
		if size[i] == 0:
			size[i] = 1
			for j in edges[i]:
				edges[j].remove(i)
				active.append(j)
		else:
			active.pop()
			edges[i].sort(key=lambda j: -size[j])
			size[i] = 1 + sum((size[j] for j in edges[i]))
	location = [None] * N
	build_tree(0, edges, location)
	return location

def root_path(i, location):
	loc = location[i]
	path = [loc]
	loc = loc[0]
	while loc.parent != None:
		path.append((loc.parent, loc.pos))
		loc = loc.parent
	path.reverse()
	return path

def max_weight(x, y):
	px = root_path(x, location)
	py = root_path(y, location)
	m = 1
	stop = min(len(px), len(py))
	while m < stop and px[m][0] == py[m][0]:
		m += 1
	(loc, a) = px[m - 1]
	b = py[m - 1][1]
	if a > b:
		(a, b) = (b, a)
	w = loc.sum_weight(b) - loc.sum_weight(a - 1)
	for j in range(m, len(px)):
		(loc, i) = px[j]
		w += loc.sum_weight(i)
	for j in range(m, len(py)):
		(loc, i) = py[j]
		w += loc.sum_weight(i)
	return w
(N, Q) = map(int, input().split())
location = read_tree(N)
for i in range(Q):
	(t, x, y) = map(int, input().split())
	if t == 1:
		(loc, i) = location[x]
		loc.set_weight(i, y)
	elif t == 2:
		print(max_weight(x, y))


class heavy_light_node:

	def __init__(self, size):
		self.parent = None
		self.pos = -1
		self.weight = [0] * size
		self.fenwick = [0] * size

	def set_weight(self, i, x):
		d = x - self.weight[i]
		self.weight[i] = x
		N = len(self.weight)
		while i < N:
			self.fenwick[i] += d
			i |= i + 1

	def sum_weight(self, i):
		if i < 0:
			return 0
		x = self.fenwick[i]
		i &= i + 1
		while i:
			x += self.fenwick[i - 1]
			i &= i - 1
		return x

def build_tree(i, edges, location):
	children = []
	members = [i]
	ed = edges[i]
	while ed:
		for j in range(1, len(ed)):
			child = build_tree(ed[j], edges, location)
			child.pos = len(members) - 1
			children.append(child)
		i = ed[0]
		members.append(i)
		ed = edges[i]
	node = heavy_light_node(len(members))
	for child in children:
		child.parent = node
	for j in range(len(members)):
		location[members[j]] = (node, j)
	return node

def read_tree(N):
	edges = [[] for i in range(N)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		edges[x].append(y)
		edges[y].append(x)
	size = [0] * N
	active = [0]
	while active:
		i = active[-1]
		if size[i] == 0:
			size[i] = 1
			for j in edges[i]:
				edges[j].remove(i)
				active.append(j)
		else:
			active.pop()
			edges[i].sort(key=lambda j: -size[j])
			size[i] = 1 + sum((size[j] for j in edges[i]))
	location = [None] * N
	build_tree(0, edges, location)
	return location

def root_path(i, location):
	loc = location[i]
	path = [loc]
	loc = loc[0]
	while loc.parent != None:
		path.append((loc.parent, loc.pos))
		loc = loc.parent
	path.reverse()
	return path

def max_weight(x, y):
	px = root_path(x, location)
	py = root_path(y, location)
	m = 1
	stop = min(len(px), len(py))
	while m < stop and px[m][0] == py[m][0]:
		m += 1
	(loc, a) = px[m - 1]
	b = py[m - 1][1]
	if a > b:
		(a, b) = (b, a)
	w = loc.sum_weight(b) - loc.sum_weight(a - 1)
	for j in range(m, len(px)):
		(loc, i) = px[j]
		w += loc.sum_weight(i)
	for j in range(m, len(py)):
		(loc, i) = py[j]
		w += loc.sum_weight(i)
	return w
(N, Q) = map(int, input().split())
location = read_tree(N)
for i in range(Q):
	(t, x, y) = map(int, input().split())
	if t == 1:
		(loc, i) = location[x]
		loc.set_weight(i, y)
	elif t == 2:
		print(max_weight(x, y))