#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
using namespace std;
const int N = 1e5 + 2;
vector<pair<int, int> > seg[3 * N][2];
long long int sig[3 * N];
int a[N];
vector<pair<int, int> > m[2];
int n, x;
inline long long int mrg(vector<pair<int, int> > z[2],
                         vector<pair<int, int> > y[2]) {
  if (z[0].size() == 0) {
    m[0] = y[0];
    m[1] = y[1];
    return 0;
  }
  if (y[0].size() == 0) {
    m[0] = z[0];
    m[1] = z[1];
    return 0;
  }
  long long int t = 0;
  for (auto i : z[1]) {
    for (auto j : y[0]) {
      if ((i.first | j.first) >= x) {
        t += 1LL * i.second * j.second;
      }
    }
  }
  m[1].clear();
  m[0].clear();
  m[1] = y[1];
  int r = 0;
  r = y[1].back().first;
  for (auto i : z[1]) {
    long long int e = (i.first | r);
    if (m[1].size() == 0) {
      m[1].push_back({e, i.second});
    } else if (e != m[1].back().first)
      m[1].push_back({e, i.second});
    else {
      m[1].back().second += i.second;
    }
  }
  m[0] = z[0];
  r = z[0].back().first;
  for (auto i : y[0]) {
    long long int e = (i.first | r);
    if (m[0].size() == 0) {
      m[0].push_back({e, i.second});
    } else if (e != m[0].back().first)
      m[0].push_back({e, i.second});
    else
      m[0].back().second += i.second;
  }
  return t;
}
void upd(int nod, int l, int r, int id, int val) {
  if (r - l == 1) {
    seg[nod][0].clear();
    seg[nod][0].push_back({val, 1});
    seg[nod][1].clear();
    seg[nod][1].push_back({val, 1});
    if (val >= x)
      sig[nod] = 1;
    else
      sig[nod] = 0;
    return;
  }
  int mid = (r + l) >> 1;
  if (mid > id)
    upd(nod << 1, l, mid, id, val);
  else
    upd(nod << 1 | 1, mid, r, id, val);
  sig[nod] = sig[nod << 1] + sig[nod << 1 | 1];
  sig[nod] += mrg(seg[nod << 1], seg[nod << 1 | 1]);
  seg[nod][0] = m[0];
  seg[nod][1] = m[1];
}
void build(int nod, int l, int r) {
  if (r - l == 1) {
    seg[nod][0].clear();
    seg[nod][0].push_back({a[l], 1});
    seg[nod][1].clear();
    seg[nod][1].push_back({a[l], 1});
    if (a[l] >= x)
      sig[nod] = 1;
    else
      sig[nod] = 0;
    return;
  }
  int mid = (r + l) >> 1;
  build(nod << 1, l, mid);
  build(nod << 1 | 1, mid, r);
  sig[nod] = sig[nod << 1] + sig[nod << 1 | 1];
  sig[nod] += mrg(seg[nod << 1], seg[nod << 1 | 1]);
  seg[nod][0] = m[0];
  seg[nod][1] = m[1];
}
vector<pair<int, int> > g[2];
long long int ans = 0;
void get(int nod, int l, int r, int L, int R) {
  if (l >= R || L >= r) return;
  if (l >= L && r <= R) {
    ans += mrg(g, seg[nod]) + sig[nod];
    g[0] = m[0];
    g[1] = m[1];
    return;
  }
  int mid = (r + l) >> 1;
  get(nod << 1, l, mid, L, R);
  get(nod << 1 | 1, mid, r, L, R);
}
int32_t main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int q;
  scanf("%d %d %d", &n, &q, &x);
  for (int i = 1; i <= n; i++) {
    scanf("%d", &a[i]);
  }
  build(1, 1, N);
  for (int i = 0; i < q; i++) {
    int t;
    scanf("%d", &t);
    if (t == 1) {
      int id, val;
      scanf("%d %d", &id, &val);
      upd(1, 1, N, id, val);
    } else {
      int l, r;
      scanf("%d %d", &l, &r);
      ans = 0;
      get(1, 1, N, l, r + 1);
      printf("%lld \n", ans);
      g[0].clear();
      g[1].clear();
    }
  }
}
