Problem:
Weighted Union Find Trees

There is a sequence $A = a_0, a_1, ..., a_{n-1}$. You are given the following information and questions.

relate$(x, y, z)$: $a_y$ is greater than $a_x$ by $z$

diff$(x, y)$: report the difference between $a_x$ and $a_y$ $(a_y - a_x)$

Input

$n \; q$
$query_1$
$query_2$
:
$query_q$

In the first line, $n$ and $q$ are given. Then, $q$ information/questions are given in the following format.

0 $x \; y\; z$

or

1 $x \; y$

where '0' of the first digit denotes the relate information and '1' denotes the diff question.

Output

For each diff question, print the difference between $a_x$ and $a_y$ $(a_y - a_x)$.

Constraints

$2 \leq n \leq 100,000$

$1 \leq q \leq 200,000$

$0 \leq x, y < n$

$x \ne y$

$0 \leq z \leq 10000$

There are no inconsistency in the given information

Sample Input

5 6
0 0 2 5
0 1 2 3
1 0 1
1 1 3
0 1 4 8
1 0 4

Sample Output

2
?
10

Solution in C (judge verdict: Accepted)

#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<inttypes.h>

typedef int32_t i32;

#define ALLOC(size,type) ((type*) calloc ((size), sizeof (type)))

typedef struct potential_union_find {
  i32 *parent;
  i32 *weight;
  i32 size;
} union_find;

union_find* new_union_find (i32 n) {
  union_find *u = ALLOC (1, union_find);
  u->parent = ALLOC (n, i32);
  u->weight = ALLOC (n, i32);
  for (i32 i = 0; i < n; ++i) {
    u->parent[i] = -1;
    u->weight[i] = 0;
  }
  return u;
}

i32 root (union_find *u, i32 x) {
  while (u->parent[x] >= 0) {
    x = u->parent[x];
  }
  return x;
}

int same (union_find *u, i32 x, i32 y) {
  return root (u, x) == root (u, y);
}

i32 get_weight (union_find *u, i32 x) {
  i32 sum = 0;
  while (u->parent[x] >= 0) {
    sum += u->weight[x];
    x = u->parent[x];
  }
  return sum;
}

int unite (union_find *u, i32 x, i32 y, i32 z) {
  z += get_weight (u, x);
  z -= get_weight (u, y);
  x = root (u, x);
  y = root (u, y);
  if (x == y) {
    return z == 0;
  }
  if (u->parent[x] > u->parent[y]) {
    i32 swap = x;
    x = y;
    y = swap;
    z = -z;
  }
  u->parent[x] += u->parent[y];
  u->parent[y] = x;
  u->weight[y] = z;
  return 1;
}

void run (void) {
  i32 n, q;
  scanf ("%" SCNi32 "%" SCNi32, &n, &q);
  union_find *u = new_union_find (n);
  while (q--) {
    i32 op, x, y;
    scanf ("%" SCNi32 "%" SCNi32 "%" SCNi32, &op, &x, &y);
    if (op == 0) {
      i32 z;
      scanf ("%" SCNi32, &z);
      if (!unite (u, x, y, z)) {
        puts ("Contradiction");
        exit (1);
      }
    } else if (!same (u, x, y)) {
      puts ("?");
    } else {
      printf ("%" PRIi32 "\n", get_weight (u, y) - get_weight (u, x));
    }
  }
}

int main (void) {
  run();
  return 0;
}