#include <bits/stdc++.h>
using namespace std;
int x;
struct node {
  vector<int> last;
  vector<int> first;
  long long cnt;
  node() : cnt(0) {}
};
vector<node> t;
vector<int> a;
void unite(node& ans, node& left, node& right) {
  ans.cnt = left.cnt + right.cnt;
  int val = 0;
  ans.last = right.last;
  for (int pos : ans.last) {
    val |= a[pos];
  }
  for (int j = 0; j < (int)(left.last).size(); ++j) {
    int pos = left.last[j];
    if ((val | a[pos]) != val || j == (int)(left.last).size() - 1) {
      ans.last.push_back(pos);
      val |= a[pos];
    }
  }
  ans.first = left.first;
  val = 0;
  for (int pos : ans.first) {
    val |= a[pos];
  }
  for (int j = 0; j < (int)(right.first).size(); ++j) {
    int pos = right.first[j];
    if ((val | a[pos]) != val || j == (int)(right.first).size() - 1) {
      ans.first.push_back(pos);
      val |= a[pos];
    }
  }
  val = 0;
  int j;
  vector<int> pre(1, 0);
  for (j = 0; j < (int)(right.first).size(); j++)
    pre.push_back((val |= a[right.first[j]]));
  val = 0;
  for (int i = 0; i < (int)(left.last).size(); ++i) {
    val |= a[left.last[i]];
    while (j > 0 && ((val | pre[j - 1]) >= x)) j--;
    if ((val | pre[j]) >= x) {
      long long lf =
          (i == (int)(left.last).size() - 1 ? 1
                                            : left.last[i] - left.last[i + 1]);
      long long rf = j ? (right.first.back() - right.first[j - 1] + 1)
                       : (right.first.back() - left.last.front());
      ans.cnt += lf * rf;
    }
  }
}
void build(int v, int tl, int tr) {
  if (tl == tr) {
    t[v].last = {tl};
    t[v].first = {tl};
    if (a[tl] >= x) {
      t[v].cnt = 1;
    } else {
      t[v].cnt = 0;
    }
    return;
  }
  int tm = (tl + tr) >> 1;
  build(v * 2, tl, tm);
  build(v * 2 + 1, tm + 1, tr);
  unite(t[v], t[v * 2], t[v * 2 + 1]);
}
void update(int v, int tl, int tr, int pos) {
  if (tl == tr) {
    t[v].last = {tl};
    t[v].first = {tl};
    if (a[tl] >= x) {
      t[v].cnt = 1;
    } else {
      t[v].cnt = 0;
    }
    return;
  }
  int tm = (tl + tr) >> 1;
  if (pos <= tm) {
    update(v * 2, tl, tm, pos);
  } else {
    update(v * 2 + 1, tm + 1, tr, pos);
  }
  unite(t[v], t[v * 2], t[v * 2 + 1]);
}
void split(int v, int tl, int tr, int l, int r, vector<node>& ans) {
  if (tl == l && tr == r) {
    ans.push_back(t[v]);
    return;
  }
  int tm = (tl + tr) >> 1;
  if (l <= tm) {
    split(v * 2, tl, tm, l, min(r, tm), ans);
  }
  if (r > tm) {
    split(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, ans);
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int n;
  cin >> n;
  int q;
  cin >> q;
  cin >> x;
  a.resize(n);
  for (int i = 0; i < n; ++i) {
    cin >> a[i];
  }
  t.resize(4 * n);
  build(1, 0, n - 1);
  while (q--) {
    int type;
    cin >> type;
    if (type == 1) {
      int pos, val;
      cin >> pos >> val;
      --pos;
      a[pos] = val;
      update(1, 0, n - 1, pos);
    } else {
      int l, r;
      cin >> l >> r;
      --l, --r;
      vector<node> vct;
      split(1, 0, n - 1, l, r, vct);
      node ans = vct[0];
      for (int i = 1; i < (int)(vct).size(); ++i) {
        node tmp;
        unite(tmp, ans, vct[i]);
        ans = tmp;
      }
      cout << ans.cnt << "\n";
    }
  }
}
