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 <string.h>
#define NMAX 100000

int ufpar[NMAX], ufw[NMAX];

int UF_find(int);
int UF_weight(int);
int UF_union(int, int, int);
int UF_diff(int*, int, int);
int main(void)
{
  int i, n, q, com, x, y, z, ans;
  scanf("%d %d", &n, &q);
  memset(ufpar, -1, sizeof(ufpar));
  for (i = 0; i < q; i++) {
    scanf("%d", &com);
    if (com) {
      scanf("%d %d", &x, &y);
      z = UF_diff(&ans, x, y);
      if (z) printf("%d\n", ans);
      else printf("?\n");
    } else {
      scanf("%d %d %d", &x, &y, &z);
      UF_union(x, y, z);
    }
  }
}

int UF_find(int a)
{
  int p;
  if (ufpar[a] < 0) return a;
  p = UF_find(ufpar[a]);
  ufw[a] += ufw[ufpar[a]];
  return ufpar[a] = p;
}

int UF_weight(int a)
{
  UF_find(a);
  return ufw[a];
}

int UF_union(int x, int y, int w)
{
  w -= UF_weight(x);
  w += UF_weight(y);
  x = UF_find(x);
  y = UF_find(y);
  if (x == y) return 0;
  if (ufpar[x] > ufpar[y]) {
    ufpar[y] += ufpar[x];
    ufpar[x] = y;
    ufw[x] = w;
  } else {
    ufpar[x] += ufpar[y];
    ufpar[y] = x;
    ufw[y] = -w;
  }
  return 1;
}

int UF_diff(int *ans, int x, int y)
{
  if (UF_find(x) != UF_find(y)) return 0;
  else {
    *ans = ufw[x] - ufw[y];
    return 1;
  }
}