Problem: 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)$

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

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)$.

Example

Input

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


Output

2
?
10

Solution (in CPP):

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

typedef long long ll;
typedef unsigned long long ull;

enum query{
    RELATE,DIFF
};

template<unsigned long long SIZE> class unionFind{
    protected:
        long long uni[SIZE];
        long long diff_weight[SIZE];
    public:
        unionFind(){
            for(int i=0;i<SIZE;i++){
                uni[i]=-1;
                diff_weight[i]=0;
            }
        }
        unsigned long long root(unsigned long long a){
            if(a>=SIZE) throw std::range_error("与えられたインデックスが木の範囲外です");
            if(uni[a]<0) return a;
            else{
                unsigned long long r=root(uni[a]);
                diff_weight[a]+=diff_weight[uni[a]];
                return uni[a]=r;
            }
        }
        long long weight(unsigned long long a){
            root(a);
            return diff_weight[a];
        }
        long long diff(unsigned long long a, unsigned long long b){
            if(isSame(a,b)) return weight(b)-weight(a);
            else return INT64_MAX;
        }
        unsigned long long count(unsigned long long a){
            return -uni[root(a)];
        }
        bool merge(unsigned long long a, unsigned long long b, long long w=1){
            w+=weight(a);  w-=weight(b);
            a=root(a);  b=root(b);
            if(a==b) return false;
            if(uni[a]>uni[b]){
                swap(a, b);
                w=(-w);
            }
            uni[a]+=uni[b];
            uni[b]=a;
            diff_weight[b]=w;
            return true;
        }
        bool isSame(unsigned long long a,unsigned long long b){
            return root(a)==root(b);
        }
};

int main(){
    unionFind<100000> uf;
    int n,q;
    cin >> n >> q;
    for(int i=0;i<q;i++){
        int c,x,y,z;
        cin >> c;
        switch(c){
            case RELATE:
                cin >> x >> y >> z;
                uf.merge(x,y,z);
                break;
            case DIFF:
                cin >> x >> y;
                if(uf.isSame(x,y)){
                    cout << uf.diff(x,y) << endl;
                }else{
                    cout << '?' << endl;
                }
        }
    }    
    
    return 0;
}