#include <bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 10;
int lim;
struct node {
  vector<pair<int, int> > suf, pre;
  long long cnt, L, R;
  node() {}
  node(int p, int v) {
    L = R = p;
    cnt = (v >= lim);
    suf.emplace_back(make_pair(v, p));
    pre.emplace_back(make_pair(v, p));
  }
};
node combine(const node& L, const node& R) {
  node ans;
  ans.cnt = L.cnt + R.cnt;
  ans.L = L.L, ans.R = R.R;
  ans.pre = L.pre, ans.suf = R.suf;
  auto tmp = L.pre.back().first;
  for (auto& i : R.pre) {
    if ((tmp | i.first) != tmp) {
      tmp |= i.first;
      ans.pre.emplace_back(make_pair(tmp, i.second));
    }
  }
  tmp = R.suf.back().first;
  for (auto& i : L.suf) {
    if ((tmp | i.first) != tmp) {
      tmp |= i.first;
      ans.suf.emplace_back(make_pair(tmp, i.second));
    }
  }
  auto f = R.pre.size() - 1;
  for (auto j = 0; j < L.suf.size(); j++) {
    auto i = L.suf[j];
    if ((i.first | R.pre[f].first) < lim) continue;
    while (f > 0 and ((i.first | R.pre[f].first) >= lim)) {
      f--;
    }
    if ((i.first | R.pre[f].first) < lim) f++;
    long long cR = ans.R - R.pre[f].second + 1;
    long long cL = i.second;
    if (j == L.suf.size() - 1)
      cL = cL - L.L + 1;
    else
      cL -= L.suf[j + 1].second;
    ans.cnt += cR * cL;
  }
  return ans;
}
int n, m;
int a[maxn];
struct segment_tree {
  node nd[maxn * 4];
  void check(int o, int L, int R) {
    cout << endl;
    cout << "[" << L << ", " << R << "]" << endl;
    cout << "cnt: " << nd[o].cnt << endl;
    if (L == R) return;
    int M = (L + R) / 2;
    check((o * 2), L, M);
    check((o * 2 + 1), M + 1, R);
  }
  void build(int o, int L, int R) {
    if (L == R) {
      nd[o] = node(L, a[L]);
      return;
    }
    int M = (L + R) / 2;
    build((o * 2), L, M);
    build((o * 2 + 1), M + 1, R);
    nd[o] = combine(nd[(o * 2)], nd[(o * 2 + 1)]);
  }
  void update(int o, int L, int R, int p, int v) {
    if (L == R)
      nd[o] = node(p, v);
    else {
      int M = (L + R) / 2;
      if (p > M)
        update((o * 2 + 1), M + 1, R, p, v);
      else
        update((o * 2), L, M, p, v);
      nd[o] = combine(nd[(o * 2)], nd[(o * 2 + 1)]);
    }
  }
  void update(int p, int v) { update(1, 1, n, p, v); }
  node query(int o, int L, int R, int ql, int qr) {
    if (ql <= L and qr >= R) return nd[o];
    int M = (L + R) / 2;
    node ans;
    if (ql <= M) {
      ans = query((o * 2), L, M, ql, qr);
      if (qr > M) ans = combine(ans, query((o * 2 + 1), M + 1, R, ql, qr));
    } else if (qr > M) {
      ans = query((o * 2 + 1), M + 1, R, ql, qr);
    }
    return ans;
  }
  long long query(int L, int R) { return query(1, 1, n, L, R).cnt; }
  void build() { build(1, 1, n); }
} tree;
void test() {}
int main() {
  scanf("%d%d%d", &n, &m, &lim);
  for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
  tree.build();
  int q, x, y;
  for (int i = 1; i <= m; i++) {
    scanf("%d%d%d", &q, &x, &y);
    if (q == 1)
      tree.update(x, y);
    else
      printf("%lld\n", tree.query(x, y));
  }
}
