#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx")
using namespace std;
using ll = int64_t;
const size_t kBuben = 10;
const int kNone = -1;
struct Pair {
  int value, count;
};
struct ByValue {
  inline bool operator()(const Pair& a, const Pair& b) const {
    return a.value < b.value;
  }
};
struct ByCount {
  inline bool operator()(const Pair& a, const Pair& b) const {
    return a.count > b.count;
  }
};
struct Segment {
  Segment* l;
  Segment* r;
  array<Pair, kBuben> top;
  int len, middle, value_to_push;
  Segment(int length) {
    l = r = nullptr;
    len = length;
    clear();
  }
  inline void clear() {
    value_to_push = kNone;
    top.fill(Pair{kNone, 0});
  }
  inline void assign(int value) {
    clear();
    top[0] = Pair{value, len};
    value_to_push = value;
  }
  inline void rebuild(const Segment& a, const Segment& b) {
    array<Pair, 2 * kBuben> result;
    array<Pair, kBuben> add;
    size_t add_count = 0;
    result.fill(Pair{kNone, 0});
    add.fill(Pair{kNone, 0});
    copy(a.top.begin(), a.top.end(), result.begin());
    sort(result.begin(), result.end(), ByValue());
    for (const auto& segment : b.top) {
      auto it = lower_bound(result.begin(), result.end(), segment, ByValue());
      if (it == result.end() || it->value != segment.value) {
        add[add_count++] = segment;
      } else {
        it->count += segment.count;
      }
    }
    copy(add.begin(), add.begin() + add_count, result.begin());
    sort(result.begin(), result.end(), ByCount());
    copy(result.begin(), result.begin() + kBuben, top.begin());
  }
};
Segment* root;
inline bool push(Segment* current) {
  if (current->value_to_push != kNone) {
    current->l->assign(current->value_to_push);
    current->r->assign(current->value_to_push);
    current->value_to_push = kNone;
    return true;
  } else {
    return false;
  }
}
inline int get_rand(int l, int r) { return l + (rand() % (r - l + 1)); }
Segment* build(int l, int r, const vector<int>& values) {
  Segment* current = new Segment(r - l + 1);
  if (l == r) {
    current->assign(values[l]);
  } else {
    int m = (l + r) / 2;
    current->middle = m;
    current->l = build(l, m, values);
    current->r = build(m + 1, r, values);
    current->rebuild(*current->l, *current->r);
  }
  return current;
}
void assign(Segment* current, int l, int r, int tl, int tr, int value) {
  if (l == tl && r == tr) {
    current->assign(value);
  } else {
    push(current);
    int m = current->middle;
    if (tl <= m) assign(current->l, l, m, tl, min(m, tr), value);
    if (tr > m) assign(current->r, m + 1, r, max(m + 1, tl), tr, value);
    current->rebuild(*current->l, *current->r);
  }
}
bool get(Segment* current, int l, int r, int tl, int tr, vector<Pair>& bests) {
  if (l == tl && r == tr) {
    for (const auto& p : current->top) {
      bests.push_back(p);
    }
    return false;
  } else {
    bool pushed = push(current);
    int m = current->middle;
    if (tl <= m) pushed |= get(current->l, l, m, tl, min(m, tr), bests);
    if (tr > m) pushed |= get(current->r, m + 1, r, max(m + 1, tl), tr, bests);
    if (pushed) current->rebuild(*current->l, *current->r);
    return pushed;
  }
}
int main() {
  srand(1224);
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  int n, m, P;
  cin >> n >> m >> P;
  int k = 100 / P;
  vector<int> values(n);
  for (int i = 0; i < n; i++) {
    cin >> values[i];
  }
  root = build(0, n - 1, values);
  vector<Pair> bests;
  vector<Pair> result;
  for (int i = 0; i < m; i++) {
    int type, l, r, id;
    cin >> type >> l >> r;
    --l, --r;
    if (type == 1) {
      cin >> id;
      assign(root, 0, n - 1, l, r, id);
    } else {
      bests.clear();
      get(root, 0, n - 1, l, r, bests);
      sort(bests.begin(), bests.end(), ByValue());
      result.clear();
      int i = 0;
      while (i < bests.size()) {
        int j = i, cnt = 0;
        while (j < bests.size() && bests[i].value == bests[j].value) {
          cnt += bests[j].count;
          ++j;
        }
        result.push_back(Pair{bests[i].value, cnt});
        i = j;
      }
      sort(result.begin(), result.end(), ByCount());
      result.resize(k);
      cout << k;
      for (const auto& x : result) {
        cout << " " << max(1, x.value);
      }
      cout << "\n";
    }
  }
  return 0;
}
