#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
long long mod = 1e9 + 7;
int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
long long lcm(long long a, long long b) { return a * (b / gcd(a, b)); }
bool is_vowel(char c) {
  if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') return 1;
  return 0;
}
double getDistance(double x1, double y1, double x2, double y2) {
  return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
long long extended_euclidean(long long a, long long b, long long &x,
                             long long &y) {
  if (b == 0) {
    x = 1;
    y = 0;
    return a;
  }
  long long g = extended_euclidean(b, a % b, y, x);
  y -= (a / b) * x;
  return g;
}
long long power(long long base, long long p) {
  if (p == 1) return base;
  if (!p) return 1ll;
  long long ret = power(base, p / 2);
  ret *= ret;
  ret %= mod;
  if (p & 1) ret *= base;
  return ret % mod;
}
struct node {
  vector<pair<int, int> > l, r;
  long long sum;
  int lft, rgt;
  node() { ; }
};
node tree[N * 4];
int a[N], n, m, x;
void merge(node &a, node b, node c) {
  a.sum = b.sum + c.sum;
  a.lft = b.lft;
  a.rgt = c.rgt;
  a.l = b.l;
  a.r = c.r;
  int cur = a.l.back().first;
  for (int i = (0); i <= ((int)c.l.size() - 1); ++i) {
    if ((cur | c.l[i].first) > cur) {
      cur |= c.l[i].first;
      a.l.push_back(pair<int, int>(cur, c.l[i].second));
    }
  }
  cur = a.r.back().first;
  for (int i = (0); i <= ((int)b.r.size() - 1); ++i) {
    if ((cur | b.r[i].first) > cur) {
      cur |= b.r[i].first;
      a.r.push_back(pair<int, int>(cur, b.r[i].second));
    }
  }
  int idx = (int)c.l.size() - 1;
  for (int i = (0); i <= ((int)b.r.size() - 1); ++i) {
    int cur = b.r[i].first;
    while (idx > 0 && (cur | c.l[idx - 1].first) >= x) idx--;
    if (cur >= x) idx = -1;
    if (idx == -1 || (cur | c.l[idx].first) >= x) {
      long long x =
          (b.r[i].second -
           (i + 1 == (int)b.r.size() ? b.lft : b.r[i + 1].second + 1) + 1) *
          1LL;
      long long y = (c.rgt - ((idx == -1) ? c.lft : c.l[idx].second) + 1) * 1LL;
      a.sum += x * y;
    }
  }
}
void build(int p, int s, int e) {
  if (s == e) {
    tree[p].l.push_back(pair<int, int>(a[s], s));
    tree[p].r.push_back(pair<int, int>(a[e], e));
    tree[p].sum = a[s] >= x;
    tree[p].lft = tree[p].rgt = s;
    return;
  }
  build(p * 2, s, (s + e) / 2);
  build(p * 2 + 1, (s + e) / 2 + 1, e);
  merge(tree[p], tree[p * 2], tree[p * 2 + 1]);
}
void update(int p, int s, int e, int idx, int val) {
  if (idx < s || e < idx) return;
  if (s == e) {
    a[s] = val;
    tree[p].l[0].first = a[s];
    tree[p].r[0].first = a[e];
    tree[p].sum = a[s] >= x;
    return;
  }
  update(p * 2, s, (s + e) / 2, idx, val);
  update(p * 2 + 1, (s + e) / 2 + 1, e, idx, val);
  merge(tree[p], tree[p * 2], tree[p * 2 + 1]);
}
node query(int p, int s, int e, int from, int to) {
  if (to < s || e < from) {
    node a;
    a.lft = -1;
    return a;
  }
  if (from <= s && e <= to) return tree[p];
  node a = query(p * 2, s, (s + e) / 2, from, to);
  node b = query(p * 2 + 1, (s + e) / 2 + 1, e, from, to);
  if (a.lft == -1) return b;
  if (b.lft == -1) return a;
  node c;
  merge(c, a, b);
  return c;
}
int main() {
  scanf("%d %d %d", &n, &m, &x);
  for (int i = (0); i <= (n - 1); ++i) scanf("%d", &a[i]);
  build(1, 0, n - 1);
  while (m--) {
    int a, b, c;
    scanf("%d %d %d", &a, &b, &c);
    if (a == 1) {
      update(1, 0, n - 1, b - 1, c);
    } else {
      printf("%I64d\n", query(1, 0, n - 1, b - 1, c - 1).sum);
    }
  }
  return 0;
}
