#include <bits/stdc++.h> using namespace std; using ll = long long; struct RB { using type = int; static type id() { return 0; } static type op(const type& l, const type & r) { return l + r; } }; struct seg_node { using M = RB; using T = typename M::type; using U = bool; T val; private: int size; bool flag; U lazy; public: seg_node() : val(), size(0), flag(false) {} void init_leaf(const T& v) { val = v; size = 1; } void init_non_leaf(const seg_node& l, const seg_node& r) { val = M::op(l.val, r.val); size = l.size + r.size; } void update(U v) { if (v) { val = size - val; } lazy ^= v; flag = true; } void push(seg_node& l, seg_node& r) { if (!flag) return; l.update(lazy); r.update(lazy); flag = false; lazy = false; } bool is_updated() const { return flag; } }; class lazy_segment_tree { using M = typename seg_node::M; using T = typename seg_node::T; using U = typename seg_node::U; const int h, n; vector<seg_node> data; void push(int node) { data[node].push(data[node << 1], data[(node << 1) | 1]); } void update(int node) { data[node].val = M::op(data[node << 1].val, data[(node << 1) | 1].val); } public: lazy_segment_tree(int n_) : h(ceil(log2(n_))), n(1 << h), data(n * 2) {} lazy_segment_tree(int n_, T v1) : h(ceil(log2(n_))), n(1 << h), data(n * 2) { for (int i = 0; i < n_; i++) data[i + n].init_leaf(v1); for (int i = n - 1; i >= 1; i--) data[i].init_non_leaf(data[i << 1], data[(i << 1) | 1]); } lazy_segment_tree(const vector<T>& data_) : h(ceil(log2(data_.size()))), n(1 << h), data(n * 2) { for (int i = 0; i < (int)data_.size(); i++) data[i + n].init_leaf(data_[i]); for (int i = n - 1; i >= 1; i--) data[i].init_non_leaf(data[i << 1], data[(i << 1) | 1]); } void update(int l, int r, U val) { l += n, r += n; for (int i = h; i > 0; i--) push(l >> i), push(r >> i); int tl = l, tr = r; r++; while (l < r) { if (l & 1) data[l++].update(val); if (r & 1) data[--r].update(val); l >>= 1; r >>= 1; } while (tl >>= 1, tr >>= 1, tl) { if (!data[tl].is_updated()) update(tl); if (!data[tr].is_updated()) update(tr); } } T find(int l, int r) { l += n, r += n; for (int i = h; i > 0; i--) push(l >> i), push(r >> i); r++; T res1 = M::id(), res2 = M::id(); while (l < r) { if (l & 1) res1 = M::op(res1, data[l++].val); if (r & 1) res2 = M::op(data[--r].val, res2); l >>= 1; r >>= 1; } return M::op(res1, res2); } }; int main() { ios::sync_with_stdio(false), cin.tie(0); int n, m, p; cin >> n >> m >> p; vector<lazy_segment_tree> lsts(17, lazy_segment_tree(n, 0)); vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; int lb = max(0, i - (p - 1)), ub = i; for (int j = 0; j < 17; j++) if (a[i] & (1 << j)) { lsts[j].update(lb, ub, true); } } while (m--) { int com; cin >> com; if (com == 1) { int i, x; cin >> i >> x; i--; int lb = max(0, i - (p - 1)), ub = i; for (int j = 0; j < 17; j++) if (x & (1 << j)) { lsts[j].update(lb, ub, true); } } else { int l, r; cin >> l >> r; l--, r--; r = min(r, n - p); ll res = 0; for (ll i = 0; i < 17; i++) { res += (ll)lsts[i].find(l, r) << i; } printf("%lld\n", res); } } return 0; }