#include <bits/stdc++.h>
using namespace std;
namespace INPUT {
const int L = 1 << 15;
char _buf[L], *S, *T, c;
char _gc() {
  if (S == T) {
    T = (S = _buf) + fread(_buf, 1, L, stdin);
    if (S == T) return EOF;
  }
  return *S++;
}
void readi(int &X) {
  for (c = _gc(); c < '0' || c > '9'; c = _gc())
    ;
  X = c & 15;
  for (c = _gc(); c >= '0' && c <= '9'; X = X * 10 + (c & 15), c = _gc())
    ;
}
}  // namespace INPUT
const int Maxn = 150005;
int T = 10;
int N, Q, P, K;
int a[Maxn];
int cnt[Maxn];
int Ansn, Ans[Maxn];
namespace SEG {
struct node {
  int n, num;
  node() { n = num = 0; }
} x[Maxn << 2][21], Val[21];
int tap[Maxn << 2];
bool cmp(node r, node c) { return r.num > c.num; }
void Updata(int i) {
  int tmp = T;
  for (int j = 1; j <= T; ++j) x[i][j] = x[i << 1][j];
  for (int k, j = 1; j <= T; ++j) {
    if (x[i << 1 | 1][j].n == 0) break;
    for (k = 1; k <= T; ++k)
      if (x[i][k].n == x[i << 1 | 1][j].n) {
        x[i][k].num += x[i << 1 | 1][j].num;
        break;
      }
    if (k > T) x[i][++tmp] = x[i << 1 | 1][j];
  }
  sort(x[i] + 1, x[i] + tmp + 1, cmp);
}
void Tap_Down(int i, int L, int R) {
  int mid = (L + R) >> 1;
  if (tap[i]) {
    tap[i << 1] = tap[i << 1 | 1] = tap[i];
    memset(x[i << 1], 0, sizeof(x[i << 1]));
    memset(x[i << 1 | 1], 0, sizeof(x[i << 1 | 1]));
    x[i << 1][1].n = x[i << 1 | 1][1].n = tap[i];
    x[i << 1][1].num = mid - L + 1, x[i << 1 | 1][1].num = R - mid;
    tap[i] = 0;
  }
}
void Merge(int i) {
  int tmp = T;
  for (int k, j = 1; j <= T; ++j) {
    if (x[i][j].n == 0) break;
    for (k = 1; k <= T; ++k)
      if (Val[k].n == x[i][j].n) {
        Val[k].num += x[i][j].num;
        break;
      }
    if (k > T) Val[++tmp] = x[i][j];
  }
  sort(Val + 1, Val + tmp + 1, cmp);
}
void Build(int i, int L, int R) {
  tap[i] = 0;
  if (L == R) {
    x[i][1].n = a[L], x[i][1].num = 1;
    return;
  }
  int mid = (L + R) >> 1;
  Build(i << 1, L, mid), Build(i << 1 | 1, mid + 1, R);
  Updata(i);
}
void Modify(int i, int L, int R, int l, int r, int X) {
  if (l <= L && r >= R) {
    tap[i] = X;
    memset(x[i], 0, sizeof(x[i]));
    x[i][1].n = X, x[i][1].num = R - L + 1;
    return;
  }
  Tap_Down(i, L, R);
  int mid = (L + R) >> 1;
  if (r <= mid)
    Modify(i << 1, L, mid, l, r, X);
  else if (l > mid)
    Modify(i << 1 | 1, mid + 1, R, l, r, X);
  else
    Modify(i << 1, L, mid, l, mid, X),
        Modify(i << 1 | 1, mid + 1, R, mid + 1, r, X);
  Updata(i);
}
void Query(int i, int L, int R, int l, int r) {
  if (l <= L && r >= R) {
    Merge(i);
    return;
  }
  Tap_Down(i, L, R);
  int mid = (L + R) >> 1;
  if (r <= mid)
    Query(i << 1, L, mid, l, r);
  else if (l > mid)
    Query(i << 1 | 1, mid + 1, R, l, r);
  else
    Query(i << 1, L, mid, l, mid), Query(i << 1 | 1, mid + 1, R, mid + 1, r);
}
void Work_Q(int L, int R) {
  memset(Val, 0, sizeof(Val));
  Query(1, 1, N, L, R);
  int Ansn = 0;
  for (int i = 1; i <= K; ++i)
    if (Val[i].n > 0) Ansn = i;
  Ansn = min(Ansn, K);
  printf("%d ", Ansn);
  for (int i = 1; i <= Ansn; ++i) printf("%d ", Val[i].n);
  puts("");
}
}  // namespace SEG
void Work1() {
  K = 100 / P;
  while (Q--) {
    int opt, l, r, x;
    INPUT::readi(opt), INPUT::readi(l), INPUT::readi(r);
    if (opt == 1) {
      INPUT::readi(x);
      for (int i = l; i <= r; ++i) a[i] = x;
    } else {
      Ansn = 0;
      int num = (r - l) * P / 100 + 1;
      for (int i = l; i <= r; ++i) ++cnt[a[i]];
      for (int i = l; i <= r; ++i) {
        if (cnt[a[i]] >= num) Ans[++Ansn] = a[i];
        cnt[a[i]] = 0;
      }
      Ansn = min(Ansn, K);
      printf("%d ", Ansn);
      for (int i = 1; i <= Ansn; ++i) printf("%d ", Ans[i]);
      puts("");
    }
  }
  exit(0);
}
void Work2() {
  K = 100 / P;
  SEG::Build(1, 1, N);
  while (Q--) {
    int opt, l, r, x;
    INPUT::readi(opt), INPUT::readi(l), INPUT::readi(r);
    if (opt == 1)
      INPUT::readi(x), SEG::Modify(1, 1, N, l, r, x);
    else
      SEG::Work_Q(l, r);
  }
  exit(0);
}
int main() {
  INPUT::readi(N), INPUT::readi(Q), INPUT::readi(P);
  for (int i = 1; i <= N; ++i) INPUT::readi(a[i]);
  if (N <= 5000 && Q <= 5000) Work1();
  Work2();
  return 0;
}
