Problem:
Charging System for Network

There is a network consisting of N machines (sequentially numbered from 0 to N-1) interconnected through N-1 bidirectional communication cables. Any two machines can perform bidirectional communication through one or more cables. From time to time, machines in the network are renewed. When a new machine is introduced, the cables directly connected to it are also replaced with thicker ones to cope with the increased volume of communication traffic.

The communication fee arising from communication traffic between any two machines is calculated by summing the charges assigned to all the cables routing via the two. A unique charging scheme is employed in this system: if the size of a cable is a multiple of K, then the cable is not charged (free of charge). Other cables are charged according to their sizes.

Based on the given information on the network topology and Q instructions, write a program to execute each instruction.

Increase the sizes of all cables directly connected to the machine x by d.

Report the communication charge between the machines s and t.

Input

The input is given in the following format.

N K
a_1 b_1 c_1
a_2 b_2 c_2
:
a_{N−1} b_{N−1} c_{N−1}
Q
query_1
query_2
:
query_Q

The first line provides the number of machines N (2 ≤ N ≤ 105) and the cable size K (1 ≤ K ≤ 105) (the reference value for determining free of charge cables). Each of subsequent N-1 lines provides the i-th cable information that directly connects two machines a_i and b_i (0 ≤ a_i < b_i ≤ N-1), followed by the cable’s initial size c_i (1 ≤ c_i ≤ 105). For any pair of machines, the number of cables directly connecting them is either one or zero. The next line following them provides the number of instructions Q (1 ≤ Q ≤ 105). Each of the Q lines following it provides the i-th instruction query_i, which is either one of the following two:

add x d

or

send s t

The instruction add x d increase the size of all cables directly connected to machine x (0 ≤ x ≤ N-1) by d (1 ≤ d ≤ 105).

The instruction send s t reports the charge imposed to the communication between the two machines s (0 ≤ s ≤ N-1) and t (0 ≤ t ≤ N-1), where s ≠ t.

At least one send instruction is included in the input information.

Output

For each send command, output the communication charge between s and t.

Sample Input 1

6 3
0 1 1
0 2 1
0 3 1
2 4 1
2 5 1
3
send 1 4
add 2 2
send 1 4

Sample Output 1

3
1

Solution in C++14 (judge verdict: Accepted)

#include <bits/stdc++.h>
using namespace std;

const int inf = 1001001001;

struct e {
  int to, cost;
  e(int to, int cost) : to(to), cost(cost) {}
};

struct edge {
  int to;
  bool edge_type;
  long long cost, scost, tcost;

  edge() {}
  // edge(int to, long long cost) : to(to), cost(cost) {}
  edge(int to, long long cost, bool edge_type, long long scost, long long tcost)
      : to(to), cost(cost), edge_type(edge_type), scost(scost), tcost(tcost) {}
};

struct query {
  bool type; // := add is true, send is false. kore eigo attennnoka
  int a, b;
  query() {}
  query(char s, int a, int b) : a(a), b(b) { type = (s == 'a'); }
};

int n, k, cnt;
vector<e> G[101010];
vector<edge> minG[101010];
query Q[1000];
int depth[101010], euler_tour[202020];
long long add[101010];
bool used[101010];

long long sqrt_int(long long n) {
  long long l = 1, r = n;
  while (r - l > 1) {
    long long m = (l + r) / 2;
    if (m * m <= n)
      l = m;
    else
      r = m;
  }
  return l;
}

inline void dfs(int v = 0, int p = -1, int d = 0) {
  // euler_tour.push_back(v);
  euler_tour[cnt++] = v;
  depth[v] = d;
  for (auto u : G[v]) {
    if (u.to == p)
      continue;
    dfs(u.to, v, d + 1);
    // euler_tour.push_back(v);
    euler_tour[cnt++] = v;
  }
}

inline void dfs2(int v, int from, int p = -1, long long cost = 0, int cnt = 0,
                 int scost = -1, int tcost = -1) {
  // cerr << v << " ( <- " << from << " )" << endl;
  if (cnt == 0) {
    for (auto u : G[v]) {
      if (u.to == p)
        continue;
      dfs2(u.to, from, v, 0, cnt + 1, u.cost + add[u.to], u.cost + add[v]);
    }
  } else if (used[v]) {

    if (cnt == 1) {
      minG[v].push_back(edge(from, scost - add[v], true, -1, -1));
      minG[from].push_back(edge(v, scost - add[v], true, -1, -1));
    } else {
      minG[v].push_back(edge(from, cost, false, tcost, scost));
      minG[from].push_back(edge(v, cost, false, scost, tcost));
    }

    dfs2(v, v, p, 0, 0, -1, -1);
  } else {
    for (auto u : G[v]) {
      if (u.to == p)
        continue;

      long long edge_cost = add[v] + add[u.to] + u.cost;
      if (used[u.to] || edge_cost % k == 0)
        edge_cost = 0;
      dfs2(u.to, from, v, cost + edge_cost, cnt + 1, scost, u.cost + add[v]);
    }
  }
}

inline bool dfs3(int s, int to, int p = -1, long long cost = 0) {
  if (s == to) {
    printf("%d\n", cost);
    // cout << cost << endl;
    return true;
  }

  for (auto u : minG[s]) {
    int t = u.to;
    if (t == p)
      continue;

    if (u.edge_type) {
      long long edge_cost = u.cost + add[s] + add[t];
      if (edge_cost % k == 0)
        edge_cost = 0;
      if (dfs3(t, to, s, cost + edge_cost))
        return true;
    } else {
      long long scost = u.scost + add[s], tcost = u.tcost + add[t];
      if (scost % k == 0)
        scost = 0;
      if (tcost % k == 0)
        tcost = 0;
      if (dfs3(t, to, s, cost + u.cost + scost + tcost))
        return true;
    }
  }
  return false;
}

void debug() {
  cout << "minimum graph" << endl;
  for (int v = 0; v < n; ++v) {
    for (auto u : minG[v])
      cout << v << " -> " << u.to << " edge_type : " << u.edge_type << " "
           << u.scost << " + " << u.cost << " + " << u.tcost << endl;
  }
}

int main() {
  scanf("%d %d", &n, &k);
  // cin >> n >> k;

  // G.resize(n);

  for (int i = 0; i < n - 1; ++i) {
    int u, v, c;
    scanf("%d %d %d", &u, &v, &c);
    // cin >> u >> v >> c;

    G[u].push_back(e(v, c));
    G[v].push_back(e(u, c));
  }

  dfs();

  int q;
  scanf("%d", &q);
  // cin >> q;

  int root_q = sqrt_int(q);
  // int root_q = 300;
  int r = (q + root_q - 1) / root_q;
  for (int p = 0; p < r; ++p) {
    int rr = min(root_q, q - p * root_q);
    // vector<query> Q;
    memset(used, false, sizeof(used));
    // minG.assign(n, vector<edge>());
    for (int i = 0; i < n; ++i)
      minG[i].clear();

    for (int i = 0; i < rr; ++i) {
      // string s;
      char s[10];
      int a, b;
      scanf("%s %d %d", s, &a, &b);
      // cin >> s >> a >> b;
      Q[i] = query(s[0], a, b);

      if (Q[i].type) {
        used[a] = true;
      } else {
        used[a] = used[b] = true;
      }
    }

    pair<int, int> mini, root;
    mini = root = make_pair(inf, -1);
    for (int i = 0; i < cnt; ++i) {
      int v = euler_tour[i];
      mini = min(mini, make_pair(depth[v], v));
      if (used[v]) {
        if (mini.second != -1)
          used[mini.second] = true;
        mini = make_pair(depth[v], v);
        root = min(root, make_pair(depth[v], v));
      }
    }

    dfs2(root.second, root.second);
    // debug();

    for (int i = 0; i < rr; ++i) {
      if (Q[i].type) {
        add[Q[i].a] += Q[i].b;
      } else {
        dfs3(Q[i].a, Q[i].b);
      }
    }
  }
}