#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const long long INFF = 0x3f3f3f3f3f3f3f3fll;
const long long M = 1e9 + 7;
const long long maxn = 1e6 + 7;
const double pi = acos(-1.0);
const double eps = 0.00000001;
long long gcd(long long a, long long b) { return b ? gcd(b, a % b) : a; }
template <typename T>
inline T abs(T a) {
  return a > 0 ? a : -a;
}
template <typename T>
inline T powMM(T a, T b) {
  T ret = 1;
  for (; b; b >>= 1ll, a = (long long)a * a % M)
    if (b & 1) ret = (long long)ret * a % M;
  return ret;
}
int X;
int A[maxn];
struct node {
  vector<pair<int, int> > L, R;
  long long ans;
} T[maxn << 2];
node merge(const node &A, const node &B) {
  node ret;
  long long orL = 0, orR = 0;
  for (auto now : A.L) orL |= now.first, ret.L.push_back(now);
  for (auto now : B.R) orR |= now.first, ret.R.push_back(now);
  for (auto now : B.L) {
    int nxt = now.first | orL;
    if (ret.L[ret.L.size() - 1].first == nxt)
      ret.L[ret.L.size() - 1].second += now.second;
    else
      ret.L.push_back(make_pair(nxt, now.second));
  }
  for (auto now : A.R) {
    int nxt = now.first | orR;
    if (ret.R[ret.R.size() - 1].first == nxt)
      ret.R[ret.R.size() - 1].second += now.second;
    else
      ret.R.push_back(make_pair(nxt, now.second));
  }
  ret.ans = A.ans + B.ans;
  long long cnt = 0;
  int i = B.L.size() - 1;
  for (auto now : A.R) {
    while (i >= 0 && (B.L[i].first | now.first) >= X) cnt += B.L[i].second, i--;
    ret.ans += (long long)now.second * cnt;
  }
  return ret;
}
void build(int x, int L, int R) {
  if (L == R) {
    T[x].L.push_back(make_pair(A[L], 1));
    T[x].R.push_back(make_pair(A[R], 1));
    T[x].ans = (A[L] >= X);
    return;
  }
  int mid = (L + R) / 2;
  build(x << 1, L, mid);
  build(x << 1 | 1, mid + 1, R);
  T[x] = merge(T[x << 1], T[x << 1 | 1]);
}
void update(int x, int pos, int L, int R) {
  if (L == R) {
    T[x].L.clear();
    T[x].R.clear();
    T[x].L.push_back(make_pair(A[L], 1));
    T[x].R.push_back(make_pair(A[R], 1));
    T[x].ans = (A[L] >= X);
    return;
  }
  int mid = (L + R) / 2;
  if (pos <= mid) update(x << 1, pos, L, mid);
  if (mid < pos) update(x << 1 | 1, pos, mid + 1, R);
  T[x] = merge(T[x << 1], T[x << 1 | 1]);
}
node query(int x, int l, int r, int L, int R) {
  if (l <= L && R <= r) return T[x];
  int mid = (L + R) / 2;
  if (r <= mid) return query(x << 1, l, r, L, mid);
  if (mid < l) return query(x << 1 | 1, l, r, mid + 1, R);
  return merge(query(x << 1, l, r, L, mid),
               query(x << 1 | 1, l, r, mid + 1, R));
}
int TaskA() {
  int n, m, i;
  scanf("%d%d%d", &n, &m, &X);
  for (i = 1; i <= n; i++) scanf("%d", &A[i]);
  build(1, 1, n);
  for (i = 1; i <= m; i++) {
    int op, l, r;
    scanf("%d%d%d", &op, &l, &r);
    if (op == 1) {
      A[l] = r;
      update(1, l, 1, n);
    } else {
      printf("%I64d\n", query(1, l, r, 1, n).ans);
    }
  }
  return 0;
}
void initialize() {}
int main() {
  int startTime = clock();
  initialize();
  fprintf(stderr, "/--- initializeTime: %ld milliseconds ---/\n",
          clock() - startTime);
  int T = 1;
  startTime = clock();
  while (T--) TaskA();
  fprintf(stderr, "/--- computeTime: %ld milliseconds ---/\n",
          clock() - startTime);
}
