#include <bits/stdc++.h>
using namespace std;
inline int read() {
  int a = 0, b = 1, c = getchar();
  while (!isdigit(c)) {
    if (c == '-') b = -b;
    c = getchar();
  }
  while (isdigit(c)) {
    a = a * 10 + c - '0';
    c = getchar();
  }
  return a * b;
}
inline void print(int x) {
  static int c[23];
  static int n;
  if (x == 0) {
    putchar('0');
    return;
  }
  if (x < 0) {
    putchar('-');
    x = -x;
  }
  n = 0;
  while (x > 0) {
    c[n++] = x % 10 + '0';
    x /= 10;
  }
  while (n-- > 0) {
    putchar(c[n]);
  }
}
inline void printsp(int x) {
  print(x);
  putchar(' ');
}
const int N = 150003;
int n, m, p;
int a[N];
class sub {
 private:
  int x[5], y[5];
  void add(int v, int t) {
    int q = 0;
    for (register int i = 0; i < p; i++) {
      if (x[i] == v) {
        y[i] += t;
        return;
      }
      if (y[i] < y[q]) q = i;
    }
    if (y[q] <= t) {
      for (register int i = 0; i < p; i++)
        if (i != q) {
          y[i] -= y[q];
        }
      t -= y[q];
      x[q] = v;
      y[q] = t;
    } else {
      for (register int i = 0; i < p; i++) {
        y[i] -= t;
      }
    }
  }

 public:
  sub() {
    for (register int i = 0; i < p; i++) {
      x[i] = 0;
      y[i] = 0;
    }
  }
  sub(const sub& b) {
    for (register int i = 0; i < p; i++) {
      x[i] = b.x[i];
      y[i] = b.y[i];
    }
  }
  sub(int v, int t) {
    for (register int i = 0; i < p; i++) {
      x[i] = 0;
      y[i] = 0;
    }
    x[0] = v;
    y[0] = t;
  }
  sub merge(const sub& b) const {
    sub ans = sub(*this);
    for (register int i = 0; i < p; i++) {
      ans.add(b.x[i], b.y[i]);
    }
    return ans;
  }
  void print() const {
    printsp(p);
    for (register int i = 0; i < p; i++) {
      printsp(x[i]);
    }
    putchar('\n');
  }
};
sub tree[4 * N];
int lazy[4 * N];
void pushup(int nod, int l, int r) {
  tree[nod] = tree[(nod << 1)].merge(tree[(nod << 1 | 1)]);
}
void pushins(int nod, int l, int r, int v) {
  tree[nod] = sub(v, r - l + 1);
  lazy[nod] = v;
}
void pushdown(int nod, int l, int r) {
  int& x = lazy[nod];
  int mid = l + (r - l) / 2;
  if (x) {
    pushins((nod << 1), l, mid, x);
    pushins((nod << 1 | 1), mid + 1, r, x);
    x = 0;
  }
}
void build(int nod, int l, int r) {
  if (l == r) {
    tree[nod] = sub(a[l], 1);
    return;
  }
  int mid = l + (r - l) / 2;
  pushdown(nod, l, r);
  build((nod << 1), l, mid);
  build((nod << 1 | 1), mid + 1, r);
  pushup(nod, l, r);
}
void ins(int nod, int l, int r, int x, int y, int z) {
  if (l == x && r == y) {
    pushins(nod, l, r, z);
    return;
  }
  int mid = l + (r - l) / 2;
  pushdown(nod, l, r);
  if (x <= mid) ins((nod << 1), l, mid, x, min(y, mid), z);
  if (y > mid) ins((nod << 1 | 1), mid + 1, r, max(mid + 1, x), y, z);
  pushup(nod, l, r);
}
sub query(int nod, int l, int r, int x, int y) {
  if (l == x && r == y) {
    return tree[nod];
  }
  int mid = l + (r - l) / 2;
  pushdown(nod, l, r);
  sub ans = sub();
  if (x <= mid) ans = ans.merge(query((nod << 1), l, mid, x, min(y, mid)));
  if (y > mid)
    ans = ans.merge(query((nod << 1 | 1), mid + 1, r, max(mid + 1, x), y));
  return ans;
}
int main() {
  n = read();
  m = read();
  p = 100 / read();
  for (int i = 1; i <= n; i++) {
    a[i] = read();
  }
  build(1, 1, n);
  for (int i = 1; i <= m; i++) {
    int op = read();
    if (op == 1) {
      int x = read();
      int y = read();
      int z = read();
      ins(1, 1, n, x, y, z);
    } else {
      int x = read();
      int y = read();
      sub ans = query(1, 1, n, x, y);
      ans.print();
    }
  }
  return 0;
}
