Use this to learn the idea, then write your own version.
123 45class Solution(object):6 def palindromePath(self, n, edges, s, queries):7 """8 :type n: int9 :type edges: List[List[int]]10 :type s: str11 :type queries: List[str]12 :rtype: List[bool]13 """14 class BIT(object): 15 def __init__(self, n):16 self.__bit = [0]*(n+1) 17 18 def add(self, i, val):19 i += 1 20 while i < len(self.__bit):21 self.__bit[i] ^= val 22 i += (i & -i)23 24 def query(self, i):25 i += 1 26 ret = 027 while i > 0:28 ret ^= self.__bit[i] 29 i -= (i & -i)30 return ret31 32 33 def build_hld(adj, cb):34 parent, depth, size, heavy, head = [-1]*len(adj), [0]*len(adj), [1]*len(adj), [-1]*len(adj), list(range(len(adj)))35 stk = [(1, 0, -1)]36 while stk:37 step, u, p = stk.pop()38 if step == 1:39 cb(u, p)40 parent[u], depth[u] = p, (depth[p]+1 if p != -1 else 0)41 stk.append((2, u, p))42 for v in adj[u]:43 if v == p:44 continue45 stk.append((1, v, u))46 elif step == 2:47 for v in adj[u]:48 if v == parent[u]:49 continue50 size[u] += size[v]51 if heavy[u] == -1 or size[v] > size[heavy[u]]:52 heavy[u] = v53 idx = -154 left, right = [-1]*len(adj), [-1]*len(adj)55 stk = [(1, 0, 0)]56 while stk:57 step, u, h = stk.pop()58 if step == 1:59 idx += 160 head[u], left[u] = h, idx61 stk.append((2, u, h))62 for v in adj[u]:63 if v == parent[u] or v == heavy[u]:64 continue65 stk.append((1, v, v))66 if heavy[u] != -1:67 stk.append((1, heavy[u], h))68 elif step == 2:69 right[u] = idx70 return parent, depth, head, left, right71 72 def lca(u, v):73 while head[u] != head[v]:74 if depth[head[u]] < depth[head[v]]:75 u, v = v, u76 u = parent[head[u]]77 return u if depth[u] < depth[v] else v78 79 def callback(u, p):80 prefix[u] = (prefix[p] if p != -1 else 0)^(1<<(ord(s[u])-ord('a')))81 82 s = list(s)83 adj = [[] for _ in xrange(n)]84 for u, v in edges:85 adj[u].append(v)86 adj[v].append(u)87 prefix = [0]*n88 parent, depth, head, left, right = build_hld(adj, callback)89 bit = BIT(n+1)90 result = []91 for q in queries:92 args = q.split()93 op = args[0]94 u = int(args[1])95 if op == "update":96 c = args[2]97 diff = (1<<(ord(s[u])-ord('a')))^(1<<(ord(c)-ord('a')))98 if not diff:99 continue100 s[u] = c101 bit.add(left[u], diff)102 bit.add(right[u]+1, diff)103 else:104 v = int(args[2])105 l = lca(u, v)106 mask = (prefix[u]^bit.query(left[u]))^(prefix[v]^bit.query(left[v]))^(1<<(ord(s[l])-ord('a')))107 result.append((mask&(mask-1)) == 0)108 return result109 110 111112113114class Solution2(object):115 def palindromePath(self, n, edges, s, queries):116 """117 :type n: int118 :type edges: List[List[int]]119 :type s: str120 :type queries: List[str]121 :rtype: List[bool]122 """123 class BIT(object): 124 def __init__(self, n):125 self.__bit = [0]*(n+1) 126 127 def add(self, i, val):128 i += 1 129 while i < len(self.__bit):130 self.__bit[i] ^= val 131 i += (i & -i)132 133 def query(self, i):134 i += 1 135 ret = 0136 while i > 0:137 ret ^= self.__bit[i] 138 i -= (i & -i)139 return ret140 141 142 class TreeInfos(object): 143 def __init__(self, adj):144 N = len(adj)145 L, R, D, P = [0]*N, [0]*N, [0]*N, [[] for _ in xrange(N)]146 idx = -1147 stk = [(1, (0, -1))]148 while stk:149 step, args = stk.pop()150 if step == 1:151 u, p = args152 D[u] = 1 if p == -1 else D[p]+1153 if p != -1:154 P[u].append(p)155 i = 0156 while i < len(P[u]) and i < len(P[P[u][i]]):157 P[u].append(P[P[u][i]][i])158 i += 1159 idx += 1160 L[u] = idx161 stk.append((2, (u,)))162 for i in reversed(xrange(len(adj[u]))):163 v = adj[u][i]164 if v == p:165 continue166 stk.append((1, (v, u)))167 elif step == 2:168 u = args[0]169 R[u] = idx170 assert(idx == N-1)171 self.L, self.R, self.D, self.P = L, R, D, P172 173 174 175 def is_ancestor(self, a, b): 176 return self.L[a] <= self.L[b] <= self.R[b] <= self.R[a]177 178 def lca(self, a, b):179 if self.D[a] > self.D[b]:180 a, b = b, a181 if self.is_ancestor(a, b):182 return a183 for i in reversed(xrange(len(self.P[a]))): 184 if i < len(self.P[a]) and not self.is_ancestor(self.P[a][i], b):185 a = self.P[a][i]186 return self.P[a][0]187 188 s = list(s)189 adj = [[] for _ in xrange(n)]190 for u, v in edges:191 adj[u].append(v)192 adj[v].append(u)193 tree_infos = TreeInfos(adj)194 bit = BIT(n+1)195 for u in xrange(n):196 diff = 1<<(ord(s[u])-ord('a'))197 bit.add(tree_infos.L[u], diff)198 bit.add(tree_infos.R[u]+1, diff)199 result = []200 for q in queries:201 args = q.split()202 op = args[0]203 u = int(args[1])204 if op == "update":205 c = args[2]206 diff = (1<<(ord(s[u])-ord('a')))^(1<<(ord(c)-ord('a')))207 if not diff:208 continue209 s[u] = c210 bit.add(tree_infos.L[u], diff)211 bit.add(tree_infos.R[u]+1, diff)212 else:213 v = int(args[2])214 l = tree_infos.lca(u, v)215 mask = bit.query(tree_infos.L[u])^bit.query(tree_infos.L[v])^(1<<(ord(s[l])-ord('a')))216 result.append(mask == 0 or (mask&(mask-1)) == 0)217 return result218