#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;
  }
}
