#include <bits/stdc++.h>
using namespace std;
const int __SIZE = 1 << 18;
char ibuf[__SIZE], *iS, *iT;
template <typename T>
inline void read(T &x) {
  char ch, t = 0;
  x = 0;
  while (!isdigit(ch = (iS == iT
                            ? (iT = (iS = ibuf) + fread(ibuf, 1, __SIZE, stdin),
                               (iS == iT ? EOF : *iS++))
                            : *iS++)))
    t |= ch == '-';
  while (isdigit(ch))
    x = x * 10 + (ch ^ 48),
    ch = (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, __SIZE, stdin),
                      (iS == iT ? EOF : *iS++))
                   : *iS++);
  x = t ? -x : x;
}
inline char read_alpha() {
  char c = (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, __SIZE, stdin),
                        (iS == iT ? EOF : *iS++))
                     : *iS++);
  while (!isalpha(c) && c != EOF)
    c = (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, __SIZE, stdin),
                     (iS == iT ? EOF : *iS++))
                  : *iS++);
  return c;
}
inline int read_int() {
  int x;
  return read(x), x;
}
inline long long read_ll() {
  long long x;
  return read(x), x;
}
template <typename T>
inline void chkmin(T &a, T b) {
  a = a < b ? a : b;
}
template <typename T>
inline void chkmax(T &a, T b) {
  a = a > b ? a : b;
}
const int MAXN = 150010;
int a[MAXN];
int tc[11];
int tx[11];
int q;
struct Ans {
  int c[6], x[6], N;
  Ans() {}
  Ans(int v, int C = 1) { N = 1, c[1] = C, x[1] = v; }
  friend Ans operator+(Ans a, Ans b) {
    int tN = 0;
    for (int i = 1; i <= b.N; i++) {
      int flag = 1;
      for (int j = 1; j <= a.N && flag; j++)
        if (a.x[j] == b.x[i]) a.c[j] += b.c[i], flag = 0;
      if (flag) ++tN, tc[tN] = b.c[i], tx[tN] = b.x[i];
    }
    for (int i = 1; i <= a.N; i++) ++tN, tc[tN] = a.c[i], tx[tN] = a.x[i];
    for (int i = 1; i <= tN; i++) {
      int flag = 0;
      for (int j = tN; j > i; j--) {
        if (tc[j] > tc[j - 1]) {
          swap(tc[j], tc[j - 1]);
          swap(tx[j], tx[j - 1]);
          flag = 1;
        }
      }
      if (!flag) break;
    }
    int cut = tN > q ? tc[q + 1] : 0;
    Ans r;
    r.N = min(tN, q);
    for (int i = 1; i <= r.N; i++) r.x[i] = tx[i], r.c[i] = tc[i] - cut;
    return r;
  }
};
struct Segment_Tree {
  struct Node {
    int tg, ad;
    Ans v;
  } T[MAXN << 2];
  inline void build(int x, int l, int r) {
    if (l == r) return T[x].v = Ans(a[l]), void();
    int mid = (l + r) >> 1;
    build((x << 1), l, mid);
    build((x << 1 | 1), mid + 1, r);
    T[x].v = T[(x << 1)].v + T[(x << 1 | 1)].v;
  }
  inline void Set(int x, int v, int len) {
    T[x].tg = v, T[x].ad = 0, T[x].v = Ans(v, len);
  }
  inline void Plus(int x, int v) {
    T[x].ad += v;
    for (int i = 1; i <= T[x].v.N; i++) T[x].v.x[i] += v;
  }
  inline void pushdown(int x, int l, int r) {
    int &tg = T[x].tg, &ad = T[x].ad, mid = (l + r) >> 1;
    int L = mid - l + 1, R = r - mid;
    if (tg) Set((x << 1), tg, L), Set((x << 1 | 1), tg, R), tg = 0;
    if (ad) Plus((x << 1), ad), Plus((x << 1 | 1), ad), ad = 0;
  }
  inline void Assign(int x, int l, int r, int L, int R, int v) {
    if (L <= l && r <= R) return Set(x, v, r - l + 1), void();
    int mid = (l + r) >> 1;
    pushdown(x, l, r);
    if (L <= mid) Assign((x << 1), l, mid, L, R, v);
    if (mid < R) Assign((x << 1 | 1), mid + 1, r, L, R, v);
    T[x].v = T[(x << 1)].v + T[(x << 1 | 1)].v;
  }
  inline void Add(int x, int l, int r, int L, int R) {
    if (L <= l && r <= R) return Plus(x, 1), void();
    int mid = (l + r) >> 1;
    pushdown(x, l, r);
    if (L <= mid) Add((x << 1), l, mid, L, R);
    if (mid < R) Add((x << 1 | 1), mid + 1, r, L, R);
    T[x].v = T[(x << 1)].v + T[(x << 1 | 1)].v;
  }
  inline Ans Q(int x, int l, int r, int L, int R) {
    if (L <= l && r <= R) return T[x].v;
    int mid = (l + r) >> 1;
    pushdown(x, l, r);
    if (R <= mid) return Q((x << 1), l, mid, L, R);
    if (mid < L) return Q((x << 1 | 1), mid + 1, r, L, R);
    return Q((x << 1), l, mid, L, R) + Q((x << 1 | 1), mid + 1, r, L, R);
  }
} seg;
int main() {
  int n = read_int(), m = read_int(), p = read_int();
  q = 100 / p;
  for (int i = 1; i <= n; i++) a[i] = read_int();
  seg.build(1, 1, n);
  for (int i = 1; i <= m; i++) {
    int op = read_int(), l = read_int(), r = read_int();
    if (op == 1) seg.Assign(1, 1, n, l, r, read_int());
    if (op == 2) {
      Ans res = seg.Q(1, 1, n, l, r);
      printf("%d", res.N);
      for (int j = 1; j <= res.N; j++) printf(" %d", res.x[j]);
      puts("");
    }
  }
  return 0;
}
