#include <bits/stdc++.h>
using namespace std;
inline char gc(void) {
  static char buf[100000], *p1 = buf, *p2 = buf;
  return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
             ? EOF
             : *p1++;
}
template <class T>
inline void read(T &x) {
  T f = 1;
  x = 0;
  static char c = getchar();
  for (; !isdigit(c); c = getchar())
    if (c == '-') f = -f;
  for (; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c & 15);
  x *= f;
}
inline void readstr(char *s) {
  do *s = getchar();
  while ((*s == ' ') || (*s == '\n') || (*s == '\r'));
  do *(++s) = getchar();
  while ((~*s) && (*s != ' ') && (*s != '\n') && (*s != '\r'));
  *s = 0;
  return;
}
inline void readch(char &x) {
  while (isspace(x = getchar()))
    ;
}
char pf[100000], *o1 = pf, *o2 = pf + 100000;
template <class T>
inline void println(T x, char c = '\n') {
  if (x < 0)
    (o1 == o2 ? fwrite(pf, 1, 100000, stdout), *(o1 = pf)++ = 45 : *o1++ = 45),
        x = -x;
  static char s[15], *b;
  b = s;
  if (!x) *b++ = 48;
  for (; x; *b++ = x % 10 + 48, x /= 10)
    ;
  for (; b-- != s; (o1 == o2          ? fwrite(pf, 1, 100000, stdout),
                    *(o1 = pf)++ = *b : *o1++ = *b))
    ;
  (o1 == o2 ? fwrite(pf, 1, 100000, stdout), *(o1 = pf)++ = c : *o1++ = c);
}
template <class T>
inline void write(T x) {
  if (x < 0) x = -x, putchar('-');
  if (x > 9) write(x / 10);
  putchar(x % 10 + 48);
}
template <class T>
inline void writeln(T x, char c = '\n') {
  write(x);
  putchar(c);
}
template <class T>
inline void chkmax(T &x, const T y) {
  x > y ? x = x : x = y;
}
template <class T>
inline void chkmin(T &x, const T y) {
  x < y ? x = x : x = y;
}
const int Maxn = 1.5e5 + 5;
int n, m, p, seq[Maxn];
struct Node {
  int cnt, tag, a[5], b[5];
  Node(void) {
    cnt = tag = 0;
    memset(a, 0, sizeof(a));
    memset(b, 0, sizeof(b));
  }
  inline Node operator=(const Node &rhs) {
    cnt = rhs.cnt;
    tag = 0;
    memcpy(a, rhs.a, sizeof a);
    memcpy(b, rhs.b, sizeof b);
    return *this;
  }
  inline Node operator+(const Node &rhs) const {
    Node ret = rhs;
    bool flg;
    for (int i = 0; i < cnt; i++) {
      flg = false;
      for (int j = 0; j < ret.cnt && !flg; j++)
        if (a[i] == ret.a[j]) flg = true, ret.b[j] += b[i];
      if (flg) continue;
      if (ret.cnt < p) {
        ret.a[ret.cnt] = a[i];
        ret.b[ret.cnt] = b[i];
        ret.cnt++;
        continue;
      }
      int k = 0;
      for (int j = 1; j < ret.cnt; j++)
        if (ret.b[j] < ret.b[k]) k = j;
      if (b[i] > ret.b[k]) {
        int val = ret.b[k];
        ret.a[k] = a[i];
        ret.b[k] = b[i];
        for (int j = 0; j < ret.cnt; j++) ret.b[j] -= val;
      } else
        for (int j = 0; j < ret.cnt; j++) ret.b[j] -= b[i];
    }
    return ret;
  }
} t[Maxn << 2];
inline void pushup(int pos) { t[pos] = t[pos << 1] + t[pos << 1 | 1]; }
inline void addtag(int pos, int len, int val) {
  t[pos].cnt = 1;
  t[pos].tag = t[pos].a[0] = val;
  t[pos].b[0] = len;
}
inline void pushdown(int pos, int l, int r) {
  if (t[pos].tag) {
    int mid = l + r >> 1;
    addtag(pos << 1, mid - l + 1, t[pos].tag);
    addtag(pos << 1 | 1, r - mid, t[pos].tag);
    t[pos].tag = 0;
  }
}
inline void build(int pos, int l, int r) {
  if (l == r) {
    t[pos].a[0] = seq[l];
    t[pos].cnt = t[pos].b[0] = 1;
    return;
  }
  int mid = l + r >> 1;
  build(pos << 1, l, mid);
  build(pos << 1 | 1, mid + 1, r);
  pushup(pos);
}
inline void modify(int pos, int l, int r, int L, int R, int val) {
  if (L <= l && R >= r) return addtag(pos, r - l + 1, val);
  int mid = l + r >> 1;
  pushdown(pos, l, r);
  if (L <= mid) modify(pos << 1, l, mid, L, R, val);
  if (R > mid) modify(pos << 1 | 1, mid + 1, r, L, R, val);
  pushup(pos);
}
inline Node query(int pos, int l, int r, int L, int R) {
  if (L <= l && R >= r) return t[pos];
  int mid = l + r >> 1;
  pushdown(pos, l, r);
  Node ret;
  if (L <= mid) ret = query(pos << 1, l, mid, L, R);
  if (R > mid) ret = ret + query(pos << 1 | 1, mid + 1, r, L, R);
  return ret;
}
signed main(void) {
  read(n), read(m), read(p);
  p = 100 / p;
  for (int i = 1; i <= n; i++) read(seq[i]);
  build(1, 1, n);
  for (int opt, l, r, val; m; m--) {
    read(opt), read(l), read(r);
    if (opt == 1) {
      read(val);
      modify(1, 1, n, l, r, val);
    } else {
      Node ret = query(1, 1, n, l, r);
      writeln(ret.cnt, ' ');
      for (int i = 0; i < ret.cnt; i++)
        writeln(ret.a[i], " \n"[i == ret.cnt - 1]);
    }
  }
  return 0;
}
