Natasha travels around Mars in the Mars rover. But suddenly it broke down, namely — the logical scheme inside it. The scheme is an undirected tree (connected acyclic graph) with a root in the vertex $1$, in which every leaf (excluding root) is an input, and all other vertices are logical elements, including the root, which is output. One bit is fed to each input. One bit is returned at the output.

There are four types of logical elements: AND ($2$ inputs), OR ($2$ inputs), XOR ($2$ inputs), NOT ($1$ input). Logical elements take values from their direct descendants (inputs) and return the result of the function they perform. Natasha knows the logical scheme of the Mars rover, as well as the fact that only one input is broken. In order to fix the Mars rover, she needs to change the value on this input.

For each input, determine what the output will be if Natasha changes this input.


-----Input-----

The first line contains a single integer $n$ ($2 \le n \le 10^6$) — the number of vertices in the graph (both inputs and elements).

The $i$-th of the next $n$ lines contains a description of $i$-th vertex: the first word "AND", "OR", "XOR", "NOT" or "IN" (means the input of the scheme) is the vertex type. If this vertex is "IN", then the value of this input follows ($0$ or $1$), otherwise follow the indices of input vertices of this element: "AND", "OR", "XOR" have $2$ inputs, whereas "NOT" has $1$ input. The vertices are numbered from one.

It is guaranteed that input data contains a correct logical scheme with an output produced by the vertex $1$.


-----Output-----

Print a string of characters '0' and '1' (without quotes) — answers to the problem for each input in the ascending order of their vertex indices.


-----Example-----
Input
10
AND 9 4
IN 1
IN 1
XOR 6 5
AND 3 7
IN 0
NOT 10
IN 1
IN 1
AND 2 8

Output
10110


-----Note-----

The original scheme from the example (before the input is changed):

[Image]

Green indicates bits '1', yellow indicates bits '0'.

If Natasha changes the input bit $2$ to $0$, then the output will be $1$.

If Natasha changes the input bit $3$ to $0$, then the output will be $0$.

If Natasha changes the input bit $6$ to $1$, then the output will be $1$.

If Natasha changes the input bit $8$ to $0$, then the output will be $1$.

If Natasha changes the input bit $9$ to $0$, then the output will be $0$.

Source: codeforces | Difficulty: HARD
Tags: Tree algorithms

Graph algorithms

Graph traversal

Implementation


Solutions:
AND = 'AND'
OR = 'OR'
XOR = 'XOR'
NOT = 'NOT'
IN = 'IN'
OPS = {AND: AND, OR: OR, XOR: XOR, NOT: NOT}

class Node:

	def __init__(self, num):
		self.num = num
		self.op = None
		self.parent = None
		self.input_1 = None
		self.input_2 = None
		self.orig_value = None
		self.root_value_if_changed = None

	@property
	def children(self):
		if self.op == IN:
			return []
		elif self.op == NOT:
			return [self.input_1]
		else:
			return [self.input_1, self.input_2]

	def can_compute(self):
		if self.op == IN:
			return True
		if self.op == NOT:
			return self.input_1.orig_value is not None
		return self.input_1.orig_value is not None and self.input_2.orig_value is not None

	def compute(self):
		if self.op == IN:
			return self.orig_value
		assert self.can_compute()
		if self.op == NOT:
			return not self.input_1.orig_value
		elif self.op == AND:
			return self.input_1.orig_value and self.input_2.orig_value
		elif self.op == OR:
			return self.input_1.orig_value or self.input_2.orig_value
		else:
			return self.input_1.orig_value != self.input_2.orig_value

	def set_input(self, a):
		self.input_1 = a
		a.parent = self

	def set_inputs(self, a, b):
		self.input_1 = a
		self.input_2 = b
		a.parent = self
		b.parent = self

def compute_orig_values(root):
	stack = [root]
	while len(stack) > 0:
		node: Node = stack[-1]
		if node.can_compute():
			node.orig_value = node.compute()
			stack.pop()
		else:
			stack.extend(node.children)

def compute_if_change(root: Node):

	def comp_if_changed(node: Node):
		if node is root:
			return not node.orig_value
		orig = node.orig_value
		node.orig_value = not node.orig_value
		res = node.parent.compute()
		node.orig_value = orig
		if res == node.parent.orig_value:
			return root.orig_value
		else:
			return node.parent.root_value_if_changed
	stack = [root]
	while len(stack) > 0:
		node: Node = stack.pop()
		node.root_value_if_changed = comp_if_changed(node)
		stack.extend(node.children)

def main():
	import sys
	n = int(sys.stdin.readline())
	nodes = {i: Node(i) for i in range(1, n + 1)}
	assert len(nodes) == n
	for i in range(1, n + 1):
		toks = sys.stdin.readline().strip().split(' ')
		node = nodes[i]
		if len(toks) == 2:
			if toks[0] == IN:
				node.op = IN
				node.orig_value = toks[1] == '1'
			else:
				node.op = NOT
				node.set_input(nodes[int(toks[1])])
		else:
			node.op = OPS[toks[0]]
			(a, b) = map(int, toks[1:])
			a = nodes[a]
			b = nodes[b]
			node.set_inputs(a, b)
	root: Node = nodes[1]
	compute_orig_values(root)
	compute_if_change(root)
	ret = []
	for i in range(1, n + 1):
		node = nodes[i]
		if node.op == IN:
			ret.append(int(node.root_value_if_changed))
	ret = ''.join((str(x) for x in ret))
	print(ret)
main()


import sys
input = sys.stdin.readline

def handle(type_, val_, u, g, S):
	if type_ == 'NOT':
		S.append(g[u][0])
	else:
		(v1, v2) = g[u]
		(val1, val2) = (Val[v1], Val[v2])
		if oper[type_](1 - val1, val2) != val_:
			S.append(v1)
		if oper[type_](val1, 1 - val2) != val_:
			S.append(v2)

def xor_(a, b):
	return a ^ b

def or_(a, b):
	return a | b

def not_(a):
	return 1 ^ a

def and_(a, b):
	return a & b
g = {}

def push(d, u, v):
	if u not in d:
		d[u] = []
	d[u].append(v)
n = int(input())
Val = [None] * n
Type = [''] * n
for i in range(n):
	arr = input().split()
	if len(arr) == 2:
		if arr[0] == 'IN':
			Type[i] = 'IN'
			Val[i] = int(arr[1])
		else:
			Type[i] = arr[0]
			push(g, i, int(arr[1]) - 1)
	else:
		(type_, v1, v2) = (arr[0], int(arr[1]), int(arr[2]))
		Type[i] = type_
		push(g, i, v1 - 1)
		push(g, i, v2 - 1)
oper = {}
oper['XOR'] = xor_
oper['OR'] = or_
oper['NOT'] = not_
oper['AND'] = and_
S = [0]
i = 0
while i < len(S):
	u = S[i]
	if u in g:
		for v in g[u]:
			S.append(v)
	i += 1
for u in S[::-1]:
	if u in g:
		type_ = Type[u]
		if len(g[u]) == 1:
			val_ = Val[g[u][0]]
			Val[u] = oper[type_](val_)
		else:
			(val_1, val_2) = (Val[g[u][0]], Val[g[u][1]])
			Val[u] = oper[type_](val_1, val_2)
ans = [0] * n
S = [0]
i = 0
while i < len(S):
	u = S[i]
	if u in g:
		(type_, val_) = (Type[u], Val[u])
		handle(type_, val_, u, g, S)
	i += 1
root_val = Val[0]
ans = [root_val] * n
for x in S:
	if Type[x] == 'IN':
		ans[x] = 1 - ans[x]
print(''.join([str(ans[x]) for x in range(n) if Type[x] == 'IN']))


import sys
n = int(input())
g = {'A': lambda a, b: v[a] & v[b], 'O': lambda a, b: v[a] | v[b], 'X': lambda a, b: v[a] ^ v[b], 'N': lambda a: v[a] ^ 1, 'I': lambda a: a + 1}

def f(q):
	q = q.split()
	return (q.pop(0)[0], [int(t) - 1 for t in q])
d = [f(q) for q in sys.stdin.readlines()]
t = [0]
for i in t:
	(f, a) = d[i]
	if f != 'I':
		t.extend(a)
v = [0] * n
for i in t[::-1]:
	(f, a) = d[i]
	v[i] = g[f](*a)
s = [0] * n
s[0] = 1
for i in t:
	if not s[i]:
		continue
	(f, a) = d[i]
	if f == 'I':
		continue
	for k in a:
		v[k] ^= 1
		s[k] = g[f](*a) != v[i]
		v[k] ^= 1
print(''.join((str(q ^ v[0]) for (q, (f, a)) in zip(s, d) if f == 'I')))


import sys
n = int(input())
f = {'AND': lambda a, b: a & b, 'OR': lambda a, b: a | b, 'XOR': lambda a, b: a ^ b, 'NOT': lambda a: a ^ 1}
g = {'0': lambda : 0, '1': lambda : 1}
d = [(g[v[0]], []) if o == 'IN' else (f[o], [int(a) - 1 for a in v]) for (o, *v) in map(str.split, sys.stdin.read().strip().split('\n'))]
q = lambda i: d[i][0](*(v[x] for x in d[i][1]))
t = [0]
for i in t:
	t.extend(d[i][1])
v = [0] * n
for i in t[::-1]:
	v[i] = q(i)
f = [0] * n
f[0] = 1
for i in t:
	if f[i] < 1:
		continue
	for k in d[i][1]:
		v[k] ^= 1
		f[k] = q(i) != v[i]
		v[k] ^= 1
print(''.join((str(f[i] ^ v[0]) for i in range(n) if not d[i][1])))


import sys
input = sys.stdin.readline
n = int(input())
stack = []
children = []
for i in range(n):
	children.append([])
parent = [-1] * n
nodes = [-1] * n
inputs = []
functions = [-1] * n
for i in range(n):
	a = list(map(str, input().split()))
	r = a[0]
	if r == 'IN':
		stack.append((i, int(a[1])))
		inputs.append(i)
	elif r == 'NOT':
		parent[int(a[1]) - 1] = i
		children[i].append(int(a[1]) - 1)
		functions[i] = 1
	else:
		x1 = int(a[1]) - 1
		x2 = int(a[2]) - 1
		parent[x1] = i
		parent[x2] = i
		children[i].append(x1)
		children[i].append(x2)
		if r == 'AND':
			functions[i] = 2
		elif r == 'XOR':
			functions[i] = 3
		else:
			functions[i] = 4
while stack:
	(pos, val) = stack.pop()
	nodes[pos] = val
	if pos == 0:
		break
	r = parent[pos]
	flag = 0
	values = []
	for child in children[r]:
		values.append(nodes[child])
	if not -1 in values:
		if functions[r] == 1:
			stack.append((r, 1 - values[0]))
		elif functions[r] == 2:
			stack.append((r, values[0] & values[1]))
		elif functions[r] == 3:
			stack.append((r, values[0] ^ values[1]))
		else:
			stack.append((r, values[0] | values[1]))
output = nodes[0]
stack = [0]
important = [0] * n
while stack:
	pos = stack.pop()
	important[pos] = 1
	if functions[pos] == -1:
		continue
	q = children[pos]
	if functions[pos] == 1:
		stack.append(q[0])
	elif functions[pos] == 2:
		if nodes[pos] == 1:
			stack.append(q[0])
			stack.append(q[1])
		elif nodes[q[0]] == 1 and nodes[q[1]] == 0:
			stack.append(q[1])
		elif nodes[q[0]] == 0 and nodes[q[1]] == 1:
			stack.append(q[0])
	elif functions[pos] == 3:
		stack.append(q[0])
		stack.append(q[1])
	elif nodes[pos] == 0:
		stack.append(q[0])
		stack.append(q[1])
	elif nodes[q[0]] == 1 and nodes[q[1]] == 0:
		stack.append(q[0])
	elif nodes[q[0]] == 0 and nodes[q[1]] == 1:
		stack.append(q[1])
ans = []
for i in inputs:
	if important[i]:
		ans.append(1 - output)
	else:
		ans.append(output)
print(''.join(map(str, ans)))