#include <bits/stdc++.h>
using namespace std;
template <class T, class U>
struct LazySegTree {
  int n;
  vector<T> dat;
  vector<U> lazy;
  T e;
  U upe;
  static void biop_assign(T &u, const T &a, const T &b) {
    int m = a[0].size();
    for (int i = (int)(0); i < (int)(2); i++) {
      for (int j = (int)(0); j < (int)(m); j++) {
        u[i][j] = a[i][b[i][j]];
      }
    }
  }
  static void upop(T &a, U b) {
    if (b == 1) {
      swap(a[0], a[1]);
    }
  }
  static U upbiop(U a, U b) { return a ^ b; }
  LazySegTree(int n_, T e, U upe) : e(e), upe(upe) {
    n = 1;
    while (n < n_) n *= 2;
    dat = vector<T>(2 * n - 1, e);
    lazy = vector<U>(2 * n - 1, upe);
  }
  void lazy_evaluate_node(int k) {
    upop(dat[k], lazy[k]);
    if (k < n - 1) {
      lazy[2 * k + 1] = upbiop(lazy[2 * k + 1], lazy[k]);
      lazy[2 * k + 2] = upbiop(lazy[2 * k + 2], lazy[k]);
    }
    lazy[k] = upe;
  }
  void update_node(int k) {
    assert(0 <= k && k < n - 1);
    biop_assign(dat[k], dat[2 * k + 1], dat[2 * k + 2]);
  }
  void update_sub(int a, int b, U v, int k, int l, int r) {
    lazy_evaluate_node(k);
    if (r <= a || b <= l) return;
    if (a <= l && r <= b) {
      lazy[k] = upbiop(lazy[k], v);
      lazy_evaluate_node(k);
      return;
    }
    int mid = (l + r) / 2;
    update_sub(a, b, v, 2 * k + 1, l, mid);
    update_sub(a, b, v, 2 * k + 2, mid, r);
    update_node(k);
  }
  void update(int a, int b, U v) { update_sub(a, b, v, 0, 0, n); }
  void update_single(int a, T val, int k, int l, int r) {
    lazy_evaluate_node(k);
    if (r <= a || a + 1 <= l) return;
    if (a <= l && r <= a + 1) {
      dat[k] = val;
      return;
    }
    int mid = (l + r) / 2;
    update_single(a, val, 2 * k + 1, l, mid);
    update_single(a, val, 2 * k + 2, mid, r);
    update_node(k);
  }
  void update_single(int a, T val) { update_single(a, val, 0, 0, n); }
  int query_sub(int a, int b, int k, int l, int r, int x) {
    lazy_evaluate_node(k);
    if (r <= a || b <= l) return x;
    if (a <= l && r <= b) return dat[k][0][x];
    int mid = (l + r) / 2;
    int vr = query_sub(a, b, 2 * k + 2, mid, r, x);
    int vl = query_sub(a, b, 2 * k + 1, l, mid, vr);
    update_node(k);
    return vl;
  }
  int query(int a, int b, int x) { return query_sub(a, b, 0, 0, n, x); }
};
int main(void) {
  int n, m, q;
  scanf("%d%d%d", &n, &m, &q);
  vector<long long int> a(n);
  for (int i = (int)(0); i < (int)(n); i++) {
    scanf("%lld", &a[i]);
    a[i] %= 2;
  }
  vector<vector<int> > id(2, vector<int>(m + 1, 0));
  for (int i = (int)(0); i < (int)(m + 1); i++) {
    id[0][i] = id[1][i] = i;
  }
  LazySegTree<vector<vector<int> >, int> lst(n, id, 0);
  for (int i = (int)(0); i < (int)(n); i++) {
    vector<vector<int> > val(2, vector<int>(m + 1, 0));
    for (int j = (int)(0); j < (int)(m); j++) {
      val[0][j] = val[1][j] = j + 1;
    }
    val[0][m] = m;
    val[1][m] = 0;
    if (a[i] == 1) {
      swap(val[0], val[1]);
    }
    lst.dat[lst.n - 1 + i] = val;
  }
  for (int i = lst.n - 2; i >= 0; --i) {
    lst.update_node(i);
  }
  for (int i = (int)(0); i < (int)(q); i++) {
    int ty;
    scanf("%d", &ty);
    if (ty == 1) {
      int l, r;
      long long int d;
      scanf("%d%d%lld", &l, &r, &d);
      l--;
      d %= 2;
      lst.update(l, r, d);
    } else {
      int l, r;
      scanf("%d%d", &l, &r);
      l--;
      int res = lst.query(l, r, m);
      printf("%d\n", res ? 1 : 2);
    }
  }
}
