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

using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vl = vector<ll>;

using _lint = int;
#define REP(i, n) for (_lint i = 0; i < (_lint)(n); i++)
#define FOR(i, a, b) for (_lint i = (_lint)(a); i < (_lint)(b); i++)
#define FORR(i, a, b) for (_lint i = (_lint)(b)-1; i >= (_lint)(a); i--)

#define CHMIN(a, b) (a) = min((a), (b))
#define CHMAX(a, b) (a) = max((a), (b))
#define ALL(v) (v).begin(), (v).end()

#define DEBUG(x) cerr << #x << ": " << (x) << endl
#define DEBUG_VEC(v)                                                           \
  {                                                                            \
    cerr << #v << ": ";                                                        \
    REP(__i, size(v)) cerr << ((v)[__i]) << ", ";                              \
    cerr << endl;                                                              \
  }

int n, m;
bool g[25][21];
bool ok[1 << 20];

ll f[1<<20][21];
ll f2[1<<20][21];
ll ff[1<<20];

int main() {
  cin >> n >> m;
  REP(i, m) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    g[a][b] = g[b][a] = true;
  }
  REP(mask, 1 << n) {
    bool go = true;
    REP(i, n) REP(j, i) {
      if (mask >> i & 1) {
        if (mask >> j & 1) {
          if (g[i][j]) {
            go = false;
          }
        }
      }
    }
    ok[mask] = go;
  }

  // https://judge.yosupo.jp/submission/4085
  REP(i,1<<n)f[i][__builtin_popcount(i)] = ok[i];
  REP(k,n)REP(i,1<<n)if(((i>>k)&1)==0)REP(j,n+1)f[i|1<<k][j]+=f[i][j];
  REP(i,1<<n)REP(j,n+1)f2[i][j] = f[i][j];
  REP(i,1<<n)FORR(j,0,n+1){
    FOR(k,1,n-j+1)f[i][j+k] += f[i][j] * f2[i][k];
    f[i][j] *= f2[i][0];
  }
  REP(k,n)REP(i,1<<n)if(((i>>k)&1)==0)REP(j,n+1)f[i|1<<k][j]-=f[i][j];
  REP(i,1<<n)ff[i]=f[i][__builtin_popcount(i)];

  ll ans = 0;
  REP(mask, 1 << n) if (ok[mask]) {
    int ho = ~mask & ((1 << n) - 1);
    ans += ff[ho];
  }
  cout << ans << endl;
  return 0;
}

// -------- START : snippet -------- //

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

struct IoSetup {
    IoSetup() {
        cin.tie(nullptr);
        ios::sync_with_stdio(false);
        cout << fixed << setprecision(10);
        cerr << fixed << setprecision(10);
    }
} iosetup;

// -------- START : macro -------- //

#define ll long long
#define rep(i,n) for(int i=0;i<int(n);++i)
#define rep1(i,n) for(int i=1;i<=int(n);++i)
#define len(c) (ll)c.size()
#define all(v) (v).begin(),(v).end()
#define lb(v,x) (lower_bound(all(v),x)-v.begin())
#define ub(v,x) (upper_bound(all(v),x)-v.begin())
#define has(c,x) (c.find(x) != c.end())
#define uniq(v) v.erase(unique(all(v)),v.end())
#define bit(k) (1LL<<(k))
#define INF int(1e9)

template<typename T1, typename T2> inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }
template<typename T1, typename T2> inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

// -------- END : macro -------- //

// -------- START : debug macro -------- //

template<class T,class U> ostream& operator<<(ostream& ost, const pair<T,U> &p) { ost << "(" << p.first << ", " << p.second << ")"; return ost; }
#define ostream_container { ost << "{"; for(const auto &t : v) { if (&t != &*v.begin()) ost << ", "; ost << t; } ost << "}"; return ost; }
template<class T> ostream& operator<<(ostream &ost, const vector<T> &v) ostream_container
template<class T> ostream& operator<<(ostream &ost, const set<T> &v) ostream_container
template<class T,class U> ostream& operator<<(ostream &ost, const map<T,U> &v) ostream_container

template<class H> void recursive_debug(string s, H h) {
    cerr << "\033[33m" << s << " = " << h << endl << "\033[m";
}
template<class H,class... T> void recursive_debug(string s, H h, T... t) {
    int comma = s.find(',');
    cerr << "\033[33m" << s.substr(0,comma) << " = " << h << ", ";
    recursive_debug(s.substr(comma+1), t...);
}
#define debug(...) recursive_debug(#__VA_ARGS__, __VA_ARGS__)

// -------- END : debug macro -------- //

// -------- END : snippet -------- //

template <typename T>
class SegmentTree{
  public:
    int n;
    T element;
    vector<T> dat;
    function<T(T,T)> operate;

    SegmentTree(){}
    SegmentTree(int n_,T element_,function<T(T,T)> operate_){
        element = element_;
        operate = operate_;
        n = 1;
        while(n < n_) n *= 2;
        dat = vector<T>(n*2,element);
    }

    void update(int k,T a){
        k += n-1;
        dat[k] = a;
        while(k > 0){
            k = (k-1)/2;
            dat[k] = operate(dat[k*2+1],dat[k*2+2]);
        }
    }

    T query(int a,int b,int k,int l,int r){
        if(r<=a || b<=l) return element;
        if(a<=l && r<=b) return dat[k];
        T vl = query(a,b,k*2+1,l,(l+r)/2);
        T vr = query(a,b,k*2+2,(l+r)/2,r);
        return operate(vl,vr);
    }

    T query(int a,int b) { return query(a,b,0,0,n); }

    T get(int k){ return query(k,k+1); }
};


int main(void) {
    int N, Q;
    cin >> N >> Q;
    vector<ll> a(N);
    SegmentTree<ll> seg(N, 0, [](ll x, ll y){ return x^y; });
    rep(i,N) {
        cin >> a[i];
        seg.update(i, a[i]);
    }
    rep(q,Q) {
        int t;
        ll x,y;
        cin >> t >> x >> y;
        if (t == 1) {
            x--;
            seg.update(x, seg.get(x) ^ y);
        } else {
            x--;
            cout << seg.query(x,y) << endl;
        }
    }
    return 0;
}
