#include <stdio.h>
#define ll long long
#define rep(i,l,r)for(int i=l;i<r;i++)
#define INF (1LL<<62)

//union-find
#define UFLIMIT (1<<17)
int unicnt[UFLIMIT+10];//正ならcnt、非正なら親のindex
ll uniwei[UFLIMIT+10];
void ufinit(int n){rep(i,0,n)unicnt[i]=1;}
int uniroot(int x){int r;return unicnt[x]<=0?r=uniroot(-unicnt[x]),uniwei[x]+=uniwei[-unicnt[x]],-(unicnt[x]=-r):x;}
int unisame(int x,int y){return uniroot(x)==uniroot(y);}
ll unidiff(int x,int y){return unisame(x,y)?uniwei[y]-uniwei[x]:INF;}
//diff(x,y)=wになるようにする。矛盾したらfalse
int uni(int x,int y,ll w){
	int rx=uniroot(x),ry=uniroot(y);
	if(rx==ry)return unidiff(rx,x)+unidiff(x,y)+unidiff(y,ry)==unidiff(rx,ry);
	w=unidiff(rx,x)+w+unidiff(y,ry);
	if(unicnt[rx]<unicnt[ry]){int t=rx;rx=ry;ry=t;w=-w;}
	unicnt[rx]+=unicnt[ry];
	unicnt[ry]=-rx;
	uniwei[ry]=w;
	return 1;
}
#undef UFLIMIT

int main(){
	int n,q;
	scanf("%d%d",&n,&q);
	ufinit(n);
	while(q--){
		int t,x,y;
		scanf("%d%d%d",&t,&x,&y);
		if(t){
			ll d=unidiff(x,y);
			printf(d==INF?"?\n":"%lld\n",d);
		}else{
			int w;
			scanf("%d",&w);
			uni(x,y,w);
		}
	}
}
