Problem:


Score : 600 points

Problem Statement

There is a tree with N vertices numbered 1 to N.
The i-th edge in this tree connects Vertex a_i and Vertex b_i, and the color and length of that edge are c_i and d_i, respectively.
Here the color of each edge is represented by an integer between 1 and N-1 (inclusive). The same integer corresponds to the same color, and different integers correspond to different colors.

Answer the following Q queries:

Query j (1 \leq j \leq Q): assuming that the length of every edge whose color is x_j is changed to y_j, find the distance between Vertex u_j and Vertex v_j. (The changes of the lengths of edges do not affect the subsequent queries.)

Constraints

2 \leq N \leq 10^5

1 \leq Q \leq 10^5

1 \leq a_i, b_i \leq N

1 \leq c_i \leq N-1

1 \leq d_i \leq 10^4

1 \leq x_j \leq N-1

1 \leq y_j \leq 10^4

1 \leq u_j < v_j \leq N

The given graph is a tree.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N Q
a_1 b_1 c_1 d_1
:
a_{N-1} b_{N-1} c_{N-1} d_{N-1}
x_1 y_1 u_1 v_1
:
x_Q y_Q u_Q v_Q

Output

Print Q lines. The j-th line (1 \leq j \leq Q) should contain the answer to Query j.

Sample Input 1

5 3
1 2 1 10
1 3 2 20
2 4 4 30
5 2 1 40
1 100 1 4
1 100 1 5
3 1000 3 4

Sample Output 1

130
200
60

The graph in this input is as follows:

Here the edges of Color 1 are shown as solid red lines, the edge of Color 2 is shown as a bold green line, and the edge of Color 4 is shown as a blue dashed line.

Query 1: Assuming that the length of every edge whose color is 1 is changed to 100, the distance between Vertex 1 and Vertex 4 is 100 + 30 = 130.

Query 2: Assuming that the length of every edge whose color is 1 is changed to 100, the distance between Vertex 1 and Vertex 5 is 100 + 100 = 200.

Query 3: Assuming that the length of every edge whose color is 3 is changed to 1000 (there is no such edge), the distance between Vertex 3 and Vertex 4 is 20 + 10 + 30 = 60. Note that the edges of Color 1 now have their original lengths.



Sample input:
5 3
1 2 1 10
1 3 2 20
2 4 4 30
5 2 1 40
1 100 1 4
1 100 1 5
3 1000 3 4


Sample output:
130
200
60

Submission status: Wrong Answer

Solution code:
#!usr/bin/env python3
from collections import defaultdict,deque
from heapq import heappush, heappop
import sys
import math
import bisect
import random
def LI(): return [int(x) for x in sys.stdin.readline().split()]
def I(): return int(sys.stdin.readline())
def LS():return [list(x) for x in sys.stdin.readline().split()]
def S(): return list(sys.stdin.readline())[:-1]
def IR(n):
    return [I() for i in range(n)]
def LIR(n):
    return [LI() for i in range(n)]
def SR(n):
    return [S() for i in range(n)]
def LSR(n):
    return [LS() for i in range(n)]

sys.setrecursionlimit(1000000)
mod = 1000000007

#A
def A():
    n,a,b = LI()
    print(min(a*n,b))
    return

#B
def B():
    n,d = LI()
    x = LIR(n)
    f = defaultdict(lambda : 0)
    for i in range(1000000):
        f[i*i] = 1
    ans = 0
    for i in range(n):
        for j in range(i+1,n):
            s = 0
            for k in range(d):
                s += (x[i][k]-x[j][k])**2
            if f[s]:
                ans += 1
    print(ans)
    return

#C
def C():
    l,r = LI()
    if r-l > 2019:
        print(0)
        quit()
    ans = float("inf")
    for i in range(l,r+1):
        for j in range(i+1,r+1):
            if i*j%2019 < ans:
                ans = i*j%2019
    print(ans)
    return

#D
def D():
    n = I()
    a = LI()
    for i in range(n):
        a[i] *= 2
    x = a[0]
    for i in range(1,n):
        if i%2:
            x -= a[i]
        else:
            x += a[i]
    b = [x//2]
    for i in range(n-1):
        b.append(abs(b[-1]-a[i]))
    print(*b)
    return

#E
def E():
    n,k = LI()
    v = [[] for i in range(n)]
    for i in range(n-1):
        a,b = LI()
        a -= 1
        b -= 1
        v[a].append(b)
        v[b].append(a)
    if k == 1:
        if n == 1:
            print(1)
            quit()
        else:
            print(0)
            quit()
    if k == 2:
        print(2)
        quit()
    d = [0]*n
    v.append([])
    v.append([])
    q = deque([0])
    bfs = [1]*n
    bfs[0] = 0
    f = [0]*n
    while q:
        x= q.popleft()
        for y in v[x]:
            if bfs[y]:
                bfs[y] = 0
                q.append(y)
    ans = 1
    q = deque([0])
    dp = [None]*n
    dp[0] = k
    bfs = [1]*n
    bfs[0] = 0
    while q:
        x = q.popleft()
        m = len(v[x])
        for y in v[x]:
            if bfs[y]:
                bfs[y] = 0
                dp[y] = k-m
                m -= 1
                q.append(y)
    for i in dp:
        ans *= i
        ans %= mod
    print(ans)
    return

#F
def F():
    def lca(x,y):
        k = depth[x]-depth[y]
        while k > 0:
            x = par[x][int(math.log(k,2))]
            k = depth[x]-depth[y]
        k = -k
        while k > 0:
            y = par[y][int(math.log(k,2))]
            k = depth[y]-depth[x]
        if x == y:
            return x
        for i in range(M+1)[::-1]:
            if par[x][i] != par[y][i]:
                x = par[x][i]
                y = par[y][i]
        return par[x][0]

    def euler_tour(x,check,color):
        for i,c,d,k in f[x]:
            if k:
                query[i] -= 2*(-color[c][0]+color[c][1]*d)
            else:
                query[i] += -color[c][0]+color[c][1]*d
        for y,c,d in v[x]:
            if not check[y]:
                check[y] = 1
                color[c][0] += d
                color[c][1] += 1
                euler_tour(y,check,color)
                check[y] = 0
                color[c][0] -= d
                color[c][1] -= 1

    M = 17 #2^17 >= 10^5
    n,Q = LI()
    v = [[] for i in range(n)]
    for i in range(n-1):
        a,b,c,d = LI()
        a -= 1
        b -= 1
        c -= 1
        v[a].append((b,c,d))
        v[b].append((a,c,d))
    par = [[] for i in range(n)]
    par[0].append(0)
    dist = [-1]*n
    dist[0] = 0
    depth = [0]*n
    q = deque([0])
    while q:
        x = q.popleft()
        for y,c,d in v[x]:
            if dist[y] < 0:
                dist[y] = dist[x]+d
                depth[y] = depth[x]+1
                q.append(y)
                par[y].append(x)

    l = [i for i in range(n)]
    l.sort(key = lambda x:depth[x])
    for i in range(M):
        for x in l:
            par[x].append(par[par[x][i]][-1])
    f = [[] for i in range(n)] #各頂点にqueryの情報を持たせる ← すごい
    query = [0]*Q #オイラーツアー、LCAを用いた距離計算により各クエリの答えを計算
    for i in range(Q):
        x,y,a,b = LI()
        x -= 1
        a -= 1
        b -= 1
        f[a].append((i,x,y,0))
        f[b].append((i,x,y,0))
        l = lca(a,b)
        f[l].append((i,x,y,1))
        query[i] = dist[a]+dist[b]-dist[l]
    check = [0]*n
    check[0] = 1
    color = [[0,0] for i in range(n)] #色ごとにオイラーツアーでdist_sum(color),num(color)を計算(その色の距離,その色の数)
    euler_tour(0,check,color)
    for i in query:
        print(i)
    return


#Solve
if __name__ == "__main__":
    F()

Submission status: Wrong Answer

Solution code:
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**7)
import numpy as np

N,Q = map(int,input().split())
graph = [[] for _ in range(N+1)]
for _ in range(N-1):
    a,b,c,d = map(int,input().split())
    graph[a].append((b,c,d))
    graph[b].append((a,c,d))
query = [[int(x) for x in input().split()] for _ in range(Q)]

def euler_tour(x, tour_v, tour_d, depth = 0, parent=None):
    tour_v.append(x)
    tour_d.append(depth)
    for y, c, d in graph[x]:
        if y == parent:
            continue
        euler_tour(y, tour_v, tour_d, depth + 1, parent = x)
        tour_v.append(x)
        tour_d.append(depth)

tour_v = []
tour_d = []
euler_tour(1, tour_v, tour_d)
tour_d_arr = np.array(tour_d)
v_to_i = {v:i for i,v in enumerate(tour_v)}
v_to_d = dict(zip(tour_v, tour_d))

# sparse table
# 各インデックスから、2^i 項目分見て、一番depthの小さいインデックス
L = len(tour_v)
U = L.bit_length()
sp = [np.arange(L)]
for i in range(1,U):
    prev = sp[-1]
    width = 1 << (i-1)
    n1 = prev[:-width]
    n2 = prev[width:]
    sp.append(np.where(tour_d_arr[n1] < tour_d_arr[n2], n1, n2))

def LCA(x,y):
    return 1
    ix = v_to_i[x]
    iy = v_to_i[y]
    if ix > iy:
        ix,iy = iy,ix
    items = iy - ix + 1
    L = items.bit_length() - 1
    n1 = sp[L][ix]
    n2 = sp[L][iy - (1 << L) + 1]
    n = n1 if tour_d[n1] < tour_d[n2] else n2
    return tour_v[n]

tasks = [[] for _ in range(N+1)]
for i,(x,y,u,v) in enumerate(query):
    tasks[u].append((i,x,y,1))
    tasks[v].append((i,x,y,1))
    tasks[LCA(u,v)].append((i,x,y,-2))

answer = [0] * Q

def dfs(x = 1, sums = [0] * (N+1), nums = [0] * (N+1), total = 0, parent = 0):
    for i,c,d,coef in tasks[x]:
        answer[i] += coef * (total - sums[c] + nums[c] * d)
    for y,c,d in graph[x]:
        if y == parent:
            continue
        sums[c] += d
        nums[c] += 1
        total += d
        dfs(y, sums, nums, total, x)
        sums[c] -= d
        nums[c] -= 1
        total -= d
    return

dfs()
print('\n'.join(map(str,answer)))

Submission status: Wrong Answer

Solution code:
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**7)
import numpy as np

N,Q = map(int,input().split())
graph = [[] for _ in range(N+1)]
for _ in range(N-1):
    a,b,c,d = map(int,input().split())
    graph[a].append((b,c,d))
    graph[b].append((a,c,d))
query = [[int(x) for x in input().split()] for _ in range(Q)]

def euler_tour(x, tour_v, tour_d, depth = 0, parent=None):
    tour_v.append(x)
    tour_d.append(depth)
    for y, c, d in graph[x]:
        if y == parent:
            continue
        euler_tour(y, tour_v, tour_d, depth + 1, parent = x)
        tour_v.append(x)
        tour_d.append(depth)

tour_v = []
tour_d = []
euler_tour(1, tour_v, tour_d)
tour_d_arr = np.array(tour_d)
v_to_i = {v:i for i,v in enumerate(tour_v)}
v_to_d = dict(zip(tour_v, tour_d))

# sparse table
# 各インデックスから、2^i 項目分見て、一番depthの小さいインデックス
L = len(tour_v)
U = L.bit_length()
sp = [np.arange(L)]
for i in range(1,U):
    prev = sp[-1]
    width = 1 << (i-1)
    n1 = prev[:-width]
    n2 = prev[width:]
    sp.append(np.where(tour_d_arr[n1] < tour_d_arr[n2], n1, n2))

def LCA(x,y):
    ix = v_to_i[x]
    iy = v_to_i[y]
    if ix > iy:
        ix,iy = iy,ix
    items = iy - ix + 1
    L = items.bit_length() - 1
    n1 = sp[L][ix]
    n2 = sp[L][iy - (1 << L) + 1]
    n = n1 if tour_d[n1] < tour_d[n2] else n2
    return tour_v[n]

Submission status: Wrong Answer

Solution code:
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**7)
import numpy as np

N,Q = map(int,input().split())
graph = [[] for _ in range(N+1)]
for _ in range(N-1):
    a,b,c,d = map(int,input().split())
    graph[a].append((b,c,d))
    graph[b].append((a,c,d))
query = [[int(x) for x in input().split()] for _ in range(Q)]

def euler_tour(x, tour_v, tour_d, depth = 0, parent=None):
    tour_v.append(x)
    tour_d.append(depth)
    for y, c, d in graph[x]:
        if y == parent:
            continue
        euler_tour(y, tour_v, tour_d, depth + 1, parent = x)
        tour_v.append(x)
        tour_d.append(depth)

tour_v = []
tour_d = []
euler_tour(1, tour_v, tour_d)
tour_d_arr = np.array(tour_d)
v_to_i = {v:i for i,v in enumerate(tour_v)}
v_to_d = dict(zip(tour_v, tour_d))

Submission status: Wrong Answer

Solution code:
from collections import defaultdict
from copy import deepcopy

def main():
    node_num, q_num = map(int, input().split())
    graph_data = defaultdict(set)
    edge_data = defaultdict(set)
    color_dist = defaultdict(int)


    for i in range(node_num - 1):
        a, b, c, d = map(int, input().split())
        graph_data[a].add(b)
        graph_data[b].add(a)
        edge_data[(a, b)] = (c, d)
        edge_data[(b, a)] = (c, d)
        color_dist[c] = d

    dist = [-1 for i in range(node_num + 1)]
    color_data = [defaultdict(int) for i in range(node_num + 1)]
    dist[1] = 0

    now_num = set()
    next_num = set()
    now_num.add(1)

    have_color = [defaultdict(int) for i in range(node_num + 1)]

    oya = [0 for i in range(node_num + 1)]
    oya[1] = 1


    while len(now_num) > 0:
        for now_ele in now_num:
            for next_ele in graph_data[now_ele]:
                if dist[next_ele] != -1:
                    continue
                # print(next_ele, now_ele)
                oya[next_ele] = now_ele
                color_data[next_ele] = deepcopy(color_data[now_ele])
                have_color[next_ele] = deepcopy(have_color[now_ele])
                # print(color_data)

                color, length = edge_data[(now_ele, next_ele)]
                dist[next_ele] = dist[now_ele] + length
                color_data[next_ele][color] += 1
                have_color[next_ele][color] += length
                next_num.add(next_ele)
        now_num = next_num
        next_num = set()

    # print(dist)
    # print(color_data)
    # print(color_dist)
    # print(have_color)

    for i in range(q_num):
        x, y, u, v = map(int, input().split())

        oya_set = set()
        u_now, v_now = u, v
        while 1:
            u_oya = oya[u_now]
            v_oya = oya[v_now]
            if u_oya in oya_set:
                oyaoya = u_oya
                break
            else:
                oya_set.add(u_oya)
            if v_oya in oya_set:
                oyaoya = v_oya
                break
            else:
                # print(v_oya)
                oya_set.add(v_oya)
            u_now, v_now = u_oya, v_oya


        u_kyori = dist[u] - (have_color[u][x] - color_data[u][x] * y)
        v_kyori = dist[v] - (have_color[v][x] - color_data[v][x] * y)
        oya_kyori = dist[oyaoya] - (have_color[oyaoya][x] - color_data[oyaoya][x] * y)
        print(abs(u_kyori + v_kyori - 2 * oya_kyori))



if __name__ == '__main__':
    main()

Submission status: Wrong Answer

Solution code:
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**7)
from collections import defaultdict

N,Q = map(int,input().split())
graph = [[] for _ in range(N+1)]
for _ in range(N-1):
    a,b,c,d = map(int,input().split())
    graph[a].append((b,c,d))
    graph[b].append((a,c,d))
query = [[int(x) for x in input().split()] for _ in range(Q)]

def set_ancestor(x=1, d=0, parent=0):
    depth[x] = d
    ax = ancestor[x]
    ax[0] = parent
    for i in range(d.bit_length() - 1):
        ax[i+1] = ancestor[ax[i]][i]
    for y, _, _ in graph[x]:
        if y == parent:
            continue
        set_ancestor(y, d+1, x)

depth = [0] * (N+1)
U = 17
ancestor = [[0] * (U+1) for _ in range(N+1)] # 2**i だけ遡った頂点の番号、行き過ぎは0
set_ancestor()

def LCA(x,y):
    dx = depth[x]
    dy = depth[y]
    if dx > dy:
        x,y = y,x
        dx,dy = dy,dx
    diff = dy - dx
    while diff:
        step = diff & (-diff)
        y = ancestor[y][step.bit_length() - 1]
        diff -= step
    while x != y:
        j = 0
        while ancestor[x][j] != ancestor[y][j]:
            j += 1
        if j == 0:
            return ancestor[x][0]
        x = ancestor[x][j-1]
        y = ancestor[y][j-1]
    return x

tasks = [[] for _ in range(N+1)]
for i,(x,y,u,v) in enumerate(query):
    tasks[u].append((i,x,y,1))
    tasks[v].append((i,x,y,1))
    tasks[LCA(u,v)].append((i,x,y,-2))

Submission status: Wrong Answer

Solution code:
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**7)
from collections import defaultdict

N,Q = map(int,input().split())
graph = [[] for _ in range(N+1)]
for _ in range(N-1):
    a,b,c,d = map(int,input().split())
    graph[a].append((b,c,d))
    graph[b].append((a,c,d))
query = [[int(x) for x in input().split()] for _ in range(Q)]

def set_ancestor(x=1, d=0, parent=0):
    depth[x] = d
    ax = ancestor[x]
    ax[0] = parent
    for i in range(d.bit_length() - 1):
        ax[i+1] = ancestor[ax[i]][i]
    for y, _, _ in graph[x]:
        if y == parent:
            continue
        set_ancestor(y, d+1, x)

depth = [0] * (N+1)
U = 17
ancestor = [[0] * (U+1) for _ in range(N+1)] # 2**i だけ遡った頂点の番号、行き過ぎは0
set_ancestor()

Submission status: Wrong Answer

Solution code:
import sys
from collections import defaultdict
sys.setrecursionlimit(10**7)
readline = sys.stdin.readline
 
N, Q = map(int, readline().split())
G = [[] for _ in range(N)]
dp = {}

for v in range(N-1):
    a, b, c, d = map(int, readline().split())
    a, b = a-1, b-1
    G[a].append(b)
    G[b].append(a)
    dp[(min(a,b), max(a,b))] = c, d
 
S = [0]*(2*N)
F = [0]*N
depth = [0]*N
depthh = [0]*N
mmn = [[0] for _ in range(N)]
msn = [[0] for _ in range(N)]
iin = [[] for _ in range(N)]
w2i = [0]*(2*N)
ii = -1
def dfs(bb, v, d, dd, cc, dpd):
    global ii
    ii += 1
    F[v] = ii-1
    depth[v] = d
    depthh[v] = dd
    S[ii] = v
    mmn[cc].append(mmn[cc][-1]+1)
    msn[cc].append(msn[cc][-1]+dpd)
    iin[cc].append(v)
    w2i[v] = ii
    for w in G[v]:
        if w == bb:
            continue
        cc, dpd = dp[(min(v,w), max(v,w))]
        dfs(v, w, d+1, dd+dpd, cc, dpd)
#        bb, v, d, dd = v, w, d+1, dd+dpd
        ii += 1
        S[ii] = v
        mmn[cc].append(mmn[cc][-1]-1)
        msn[cc].append(msn[cc][-1]-dpd)
        iin[cc].append(-w)
        w2i[-w] = ii


dfs(None, 0, 0, 0, 0,0)
lnc = [len(x)-1 for x in mmn]
 
INF = (N, None)
M = 2*N
M0 = 2**(M-1).bit_length()
data = [INF]*(2*M0)
for i, v in enumerate(S):
    data[M0-1+i] = (depth[v], i)
for i in range(M0-2, -1, -1):
    data[i] = min(data[2*i+1], data[2*i+2])
 
def _query(a, b):
    yield INF
    a += M0; b += M0
    while a < b:
        if b & 1:
            b -= 1
            yield data[b-1]
        if a & 1:
            yield data[a-1]
            a += 1
        a >>= 1; b >>= 1
 
def query(u, v):
    fu = F[u]; fv = F[v]
    if fu > fv:
        fu, fv = fv, fu
    return S[min(_query(fu, fv+1))[1]]

def b_s(ll, mm, ms, ind, lw, hw, target_i, lncc):
    if target_i < w2i[ll[0]]:
        return 0, 0
    if target_i >= w2i[ll[lncc]]:
        return 0, 0
    while True:
        if w2i[ll[ind]] <= target_i:
            if target_i < w2i[ll[ind+1]]:
                return (mm[ind+1], ms[ind+1])
            ind, lw = (ind+1 + hw)//2, ind+1
            continue
        ind, hw = (ind-1 + lw)//2, ind-1

def iro(u, v, cc, x, y):
    u_n, u_d = b_s(iin[x], mmn[x], msn[x], (lnc[x]-1)//2, 0, lnc[x]-1, w2i[u], lnc[x]-1)
    v_n, v_d = b_s(iin[x], mmn[x], msn[x], (lnc[x]-1)//2, 0, lnc[x]-1, w2i[v], lnc[x]-1)
    c_n, c_d = b_s(iin[x], mmn[x], msn[x], (lnc[x]-1)//2, 0, lnc[x]-1, w2i[cc], lnc[x]-1)
    return (u_n + v_n - 2 * (c_n)) * y - (u_d + v_d - 2 * (c_d))

for q in range(Q):
    x, y, u, v = map(int, readline().split())
    u, v = u-1, v-1
    cc = query(u, v)
    if lnc[x] == 0:
        diff = 0
    else:
        diff = iro(u, v, cc, x, y)
    print(depthh[u] + depthh[v] - 2*depthh[cc] + diff)

Submission status: Wrong Answer

Solution code:
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**6)
from bisect import bisect_right as br

N, K = map(int, input().split())
X = [[] for i in range(N)]
for i in range(N-1):
    x, y, c, d = map(int, input().split())
    X[x-1].append((y-1, c-1, d))
    X[y-1].append((x-1, c-1, d))

P = [(-1, 0, 0)] * N
Q = [0]
R = []
ET = []
done = [0] * N
ct = 0
CT = [0] * (N-1) * 2
CTA = [-1]* N
BT = [[[-1], [0], [0]] for _ in range(N)] # id, cnt, sum
# BT = [[] for _ in range(N)] # id, cnt, sum
# BT = [[-1]*N] + [[0]*N] + [[0]*N]
def dfs(i):
    global ct
    if done[i]:
        return 0
    R.append(i)
    done[i] = 1
    for a, c, d in X[i]:
        if a != P[i][0]:
            ET.append((i, a))
            P[a] = (i, c, d)
            for k in range(len(X[a])):
                if X[a][k][0] == i:
                    del X[a][k]
                    break
            # print(i, "->", a)
            if CTA[a] < 0: CTA[a] = ct
            BT[c][0].append(ct)
            BT[c][1].append(BT[c][1][-1]+1)
            BT[c][2].append(BT[c][2][-1]+d)
            ct += 1
            dfs(a)
            BT[c][0].append(ct)
            BT[c][1].append(BT[c][1][-1]-1)
            BT[c][2].append(BT[c][2][-1]-d)
            ct += 1
            # print(a, "->", i)

dfs(0)

Submission status: Wrong Answer

Solution code:
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**6)
from bisect import bisect_right as br

N, K = map(int, input().split())
X = [[] for i in range(N)]
for i in range(N-1):
    x, y, c, d = map(int, input().split())
    X[x-1].append((y-1, c-1, d))
    X[y-1].append((x-1, c-1, d))

P = [(-1, 0, 0)] * N
Q = [0]
R = []
ET = []
done = [0] * N
ct = 0
CT = [0] * (N-1) * 2
CTA = [-1]* N
BT = [[[-1], [0], [0]] for _ in range(N)] # id, cnt, sum
# BT = [[] for _ in range(N)] # id, cnt, sum
# BT = [[-1]*N] + [[0]*N] + [[0]*N]
def dfs(i):
    global ct
    if done[i]:
        return 0
    R.append(i)
    done[i] = 1
    for a, c, d in X[i]:
        if a != P[i][0]:
            ET.append((i, a))
            P[a] = (i, c, d)
            for k in range(len(X[a])):
                if X[a][k][0] == i:
                    del X[a][k]
                    break
            # print(i, "->", a)
            if CTA[a] < 0: CTA[a] = ct
            BT[c][0].append(ct)
            BT[c][1].append(BT[c][1][-1]+1)
            BT[c][2].append(BT[c][2][-1]+d)
            ct += 1
            dfs(a)
            BT[c][0].append(ct)
            BT[c][1].append(BT[c][1][-1]-1)
            BT[c][2].append(BT[c][2][-1]-d)
            ct += 1
            # print(a, "->", i)

dfs(0)
L = [[0, 0] for _ in range(N)] # depth, dist, list
# print("BT =", BT)
# print("CTA =", CTA)

for i in R[1:]:
    p, c, d = P[i]
    L[i][0] = L[p][0] + 1
    L[i][1] = L[p][1] + d

D = [[P[i][0] for i in range(N)]] + [[-1]*N for _ in range(16)]
for k in range(1, 17):
    for i in range(N):
        a = D[k-1][i]
        if a > 0:
            D[k][i] = D[k-1][a]

Submission status: Wrong Answer

Solution code:
import sys
sys.setrecursionlimit(1000000)

from bisect import bisect_right as br
N, K = map(int, input().split())
X = [[] for i in range(N)]
for i in range(N-1):
    x, y, c, d = map(int, input().split())
    X[x-1].append((y-1, c-1, d))
    X[y-1].append((x-1, c-1, d))

P = [(-1, 0, 0)] * N
Q = [0]
R = []
ET = []
done = [0] * N
ct = 0
CT = [0] * (N-1) * 2
CTA = [-1]* N
BT = [[[-1], [0], [0]] for _ in range(N)] # id, cnt, sum
# BT = [[] for _ in range(N)] # id, cnt, sum
# BT = [[-1]*N] + [[0]*N] + [[0]*N]
def dfs(i):
    global ct
    if done[i]:
        return 0
    R.append(i)
    done[i] = 1
    for a, c, d in X[i]:
        if a != P[i][0]:
            ET.append((i, a))
            P[a] = (i, c, d)
            for k in range(len(X[a])):
                if X[a][k][0] == i:
                    del X[a][k]
                    break
            # print(i, "->", a)
            if CTA[a] < 0: CTA[a] = ct
            BT[c][0].append(ct)
            BT[c][1].append(BT[c][1][-1]+1)
            BT[c][2].append(BT[c][2][-1]+d)
            ct += 1
            dfs(a)
            BT[c][0].append(ct)
            BT[c][1].append(BT[c][1][-1]-1)
            BT[c][2].append(BT[c][2][-1]-d)
            ct += 1
            # print(a, "->", i)

dfs(0)
L = [[0, 0] for _ in range(N)] # depth, dist, list
# print("BT =", BT)
# print("CTA =", CTA)

for i in R[1:]:
    p, c, d = P[i]
    L[i][0] = L[p][0] + 1
    L[i][1] = L[p][1] + d

D = [[P[i][0] for i in range(N)]] + [[-1]*N for _ in range(16)]
for k in range(1, 17):
    for i in range(N):
        a = D[k-1][i]
        if a > 0:
            D[k][i] = D[k-1][a]


def lca(u0, v0):
    u, v = u0, v0
    if L[u][0] < L[v][0]:
        u, v = v, u
    
    while L[u][0] > L[v][0]:
        d = L[u][0] - L[v][0]
        dd = d.bit_length() - 1
        u = D[dd][u]
    if u == v:
        return u
    
    for i in range(17)[::-1]:
        if D[i][u] != D[i][v]:
            u = D[i][u]
            v = D[i][v]
    
    return D[0][u]
    

def calc(x, y, w):
    # print("calc ", x, y, w)
    aa = br(BT[x][0], CTA[w]) - 1
        
    # print("aa =", aa)
    # print("BT =", BT)
    c = BT[x][1][aa]
    d = BT[x][2][aa]
    # print(x, y, w, aa, c, d, L[w][1])
    return L[w][1] + c*y - d

for _ in range(min(K, 10000)):
    x, y, u, v = map(int, input().split())
    x, u, v = x-1, u-1, v-1
    
    ll = lca(u, v)
    print(calc(x, y, u) + calc(x, y, v) - 2*calc(x, y, ll))
    # print(calc(x, y, u, v))

Submission status: Wrong Answer

Solution code:
from collections import deque,defaultdict
import sys
sys.setrecursionlimit(10**7)
N,Q=map(int,input().split())
table=[[] for i in range(N)]
ddcost=defaultdict(tuple)
for i in range(N-1):
    a,b,c,d=map(int,input().split())
    a,b,c=a-1,b-1,c-1
    table[a].append(b)
    table[b].append(a)
    ddcost[(min(a,b),max(b,a))]=(c,d)
#print(table)
#print(ddcost)
H=deque()
H.append(0)
visit=[-1]*N
visit[0]=0
parent=[[-1]*N for i in range(18)]
while H:
    x=H.popleft()
    for y in table[x]:
        if visit[y]!=-1:
            continue
        parent[0][y]=x
        visit[y]=visit[x]+1
        H.append(y)
for k in range(17):
    for i in range(N):
        if parent[k][i]<0:
            parent[k+1][i]=-1
        else:
            parent[k + 1][i]=parent[k][parent[k][i]]
def lca(u,v):
    if visit[u]>visit[v]:
        u,v=v,u
    for k in range(18):
        if ((visit[v]-visit[u] )>>k)%1:
            v=parent[k][v]
    if u==v:
        return u
    for k in range(17,-1,-1):
        if parent[k][u]!=parent[k][v]:
            u=parent[k][u]
            v=parent[k][v]
    return parent[0][u]

query=[]
sakidori=[set() for i in range(N)]
for i in range(Q):
    x,y,u,v=map(int,input().split())
    x,u,v=x-1,u-1,v-1
    if u>=v:
        u,v=v,u
    pa=lca(u,v)
    sakidori[u].add(x)
    sakidori[v].add(x)
    sakidori[pa].add(x)
    query.append((x,y,u,v,pa))
ddcolorsum=defaultdict(int)
ddcolornum=defaultdict(int)
W=deque()
colorsum=[0]*(N-1)
colornum=[0]*(N-1)
dist=[0]*N
vi=[0]*N
W.append((0,0,1))

while W:
    pa,ci,vector=W.pop()
    if vector==-1:
        color,dis=ddcost[(min(pa,ci),max(pa,ci))]
        colorsum[color]-=dis
        colornum[color]-=1
        continue
    if pa==0 and ci==0:
        for y in table[ci]:
            W.append((ci, y, 1))
        for co in sakidori[0]:
            ddcolorsum[(0,co)]=0
            ddcolornum[(0,co)]=0
        continue
    color,dis=ddcost[(min(pa,ci),max(pa,ci))]
    dist[ci]+=dist[pa]+dis
    colorsum[color]+=dis
    colornum[color]+=1
    for co in sakidori[ci]:
        ddcolorsum[(ci, co)] = colorsum[co]
        ddcolornum[(ci, co)] = colornum[co]
    W.append((pa,ci,-1))
    for y in table[ci]:
        if y==pa:
            continue
        W.append((ci,y,1))
#print(ddcolorsum)
#print(ddcolornum)
#print(dist)
def dista(x,y,u):
    return dist[u]-ddcolorsum[(u,x)]+y*ddcolornum[(u,x)]
for x,y,u,v,pa in query:
    #print(x,y,u,v,pa)
    #print(dista(x,y,u),dista(x,y,v),dista(x,y,pa))
    print(dista(x,y,u)+dista(x,y,v)-2*dista(x,y,pa))

Submission status: Wrong Answer

Solution code:
import sys
from collections import defaultdict
sys.setrecursionlimit(10**7)
 
readline = sys.stdin.readline
write = sys.stdout.write
 
N, Q = map(int, readline().split())
G = [[] for _ in range(N)]
g = defaultdict(list)
dp = {}
cdd = {}

for v in range(N-1):
    a, b, c, d = map(int, readline().split())
    a, b = a-1, b-1
    g[a].append(b)
    g[b].append(a)
    dp["{}-{}".format(min(a,b), max(a,b))] = d
    cdd["{}-{}".format(min(a,b), max(a,b))] = c
cc = set()
i = 0
imkr = set()
while True:
    cc.add(i)
    for vv in g[i]:
        if vv not in cc:
            G[i].append(vv)
            imkr.add(vv)
    if len(imkr) == 0:
        break
    i = imkr.pop()
 
S = []
F = [0]*N
depth = [0]*N
depthh = [0]*N
vn = [[] for _ in range(N)]
sn = [[] for _ in range(N)]
iin = [[] for _ in range(N)]
aii = []
w2i = [0]*(2*N)

ii = 0
def dfs(bb, v, d, dd, cc, dpd):
    global ii
    F[v] = len(S)
    depth[v] = d
    depthh[v] = dd
    S.append(v)
    vn[cc].append(1)
    sn[cc].append(dpd)
    iin[cc].append(v)
    aii.append(v)
    w2i[v] = ii
    ii += 1
    for w in G[v]:
        nvn = cdd["{}-{}".format(min(v,w), max(v,w))]
        dpd = dp["{}-{}".format(min(v,w), max(v,w))]
        dfs(v, w, d+1, dd+dpd, nvn, dpd)
        S.append(v)
        vn[nvn].append(-1)
        sn[nvn].append(-dpd)
        iin[nvn].append(-w)
        aii.append(-w)
        w2i[-w] = ii
        ii += 1

dfs(None, 0, 0, 0, 0,0)
#print(S)
#print(vn)
#print(sn)
#print(iin)
#print(aii)
#print(w2i)
from itertools import accumulate
mmn = []
lnc = []
for vvv in vn:
    lnc.append(len(vvv))
    mmn.append(list(accumulate(vvv)))
msn = []
for vvv in sn:
    msn.append(list(accumulate(vvv)))
 
INF = (N, None)
 
M = 2*N
M0 = 2**(M-1).bit_length()
data = [INF]*(2*M0)
for i, v in enumerate(S):
    data[M0-1+i] = (depth[v], i)
for i in range(M0-2, -1, -1):
    data[i] = min(data[2*i+1], data[2*i+2])
 
def _query(a, b):
    yield INF
    a += M0; b += M0
    while a < b:
        if b & 1:
            b -= 1
            yield data[b-1]
        if a & 1:
            yield data[a-1]
            a += 1
        a >>= 1; b >>= 1
 
def query(u, v):
    fu = F[u]; fv = F[v]
    if fu > fv:
        fu, fv = fv, fu
    return S[min(_query(fu, fv+1))[1]]

def b_s(ll, mm, ms, ind, lw, hw, target_i, lncc):
    if w2i[ll[ind]] <= target_i:
        if ind+1 >= len(ll):
            return 0, 0
        if target_i < w2i[ll[ind+1]]:
            return (mm[ind], ms[ind])
        return b_s(ll, mm, ms, (ind+1 + hw)//2, ind+1, hw, target_i, lncc)
    elif w2i[ll[ind]] > target_i:
        return b_s(ll, mm, ms, (ind + lw)//2, lw, ind-1, target_i, lncc)
    return 0, 0

def iro(u, v, cc, x, y):
    return 0
    if w2i[u] < w2i[iin[x][0]]:
        u_n, u_d = 0, 0
    else:
        u_n, u_d = b_s(iin[x], mmn[x], msn[x], (lnc[x]-1)//2, 0, lnc[x]-1, w2i[u], lnc[x]-1)
    if w2i[v] < w2i[iin[x][0]]:
        v_n, v_d = 0, 0
    else:
        v_n, v_d = b_s(iin[x], mmn[x], msn[x], (lnc[x]-1)//2, 0, lnc[x]-1, w2i[v], lnc[x]-1)
    if w2i[cc] < w2i[iin[x][0]]:
        c_n, c_d = 0, 0
    else:
        c_n, c_d = b_s(iin[x], mmn[x], msn[x], (lnc[x]-1)//2, 0, lnc[x]-1, w2i[cc], lnc[x]-1)
    return (u_n + v_n - 2 * (c_n)) * y - (u_d + v_d - 2 * (c_d))

 
 
for q in range(Q):
    x, y, u, v = map(int, readline().split())
    u, v = u-1, v-1
    cc = query(u, v)
    diff = 0
    if lnc[x] == 0:
        diff = 0
    else:
        diff = iro(u, v, cc, x, y)
#    print("query, col : {} v_ind : {}".format(x, v), b_s(iin[x], mmn[x], msn[x], (lnc[x]-1)//2, 0, lnc[x]-1, w2i[v], lnc[x]-1))
    print(depthh[u] + depthh[v] - 2*depthh[cc] + diff)