#include <bits/stdc++.h>
using namespace std;
int n, P, a[150005], lazy_tag[600005], m;
int read() {
  char x = getchar();
  int ans = 0;
  while (!isdigit(x)) x = getchar();
  while (isdigit(x)) ans = ans * 10 + x - '0', x = getchar();
  return ans;
}
struct node {
  vector<pair<int, int> > V;
  void clear() { V.clear(); }
  int size() { return (int)V.size(); }
  void push_back(pair<int, int> x) { V.push_back(x); }
  node operator+(node x) {
    if (V.empty()) return x;
    node ans = *this;
    for (int i = 0; i < x.size(); i++) {
      bool flag = 0;
      for (int j = 0; j < ans.V.size(); j++)
        if (ans.V[j].first == x.V[i].first) {
          flag = 1, ans.V[j].second += x.V[i].second;
          break;
        }
      if (flag) continue;
      ans.V.push_back(x.V[i]);
      if (ans.V.size() <= P) continue;
      int minn = 1e9;
      for (int j = 0; j < ans.V.size(); j++) minn = min(minn, ans.V[j].second);
      vector<pair<int, int> > tmp;
      for (int j = 0; j < ans.V.size(); j++)
        if (ans.V[j].second - minn)
          tmp.push_back(make_pair(ans.V[j].first, ans.V[j].second - minn));
      ans.V = tmp;
    }
    return ans;
  }
} tree[600005];
int ls(int p) { return p << 1; }
int rs(int p) { return p << 1 | 1; }
void pushup(int p) { tree[p] = tree[ls(p)] + tree[rs(p)]; }
void build(int l, int r, int p) {
  if (l == r) {
    tree[p].push_back(make_pair(a[l], 1));
    return;
  }
  int mid = (l + r) >> 1;
  build(l, mid, ls(p));
  build(mid + 1, r, rs(p));
  pushup(p);
}
void pushdown(int p, int l, int r) {
  if (!lazy_tag[p]) return;
  lazy_tag[ls(p)] = lazy_tag[rs(p)] = lazy_tag[p];
  tree[ls(p)].clear(), tree[rs(p)].clear();
  int mid = (l + r) >> 1;
  tree[ls(p)].push_back(make_pair(lazy_tag[p], mid - l + 1));
  tree[rs(p)].push_back(make_pair(lazy_tag[p], r - mid));
  lazy_tag[p] = 0;
}
void update(int l, int r, int ll, int rr, int p, int val) {
  if (ll <= l && r <= rr) {
    tree[p].clear();
    lazy_tag[p] = val;
    tree[p].push_back(make_pair(val, r - l + 1));
    return;
  }
  int mid = (l + r) >> 1;
  pushdown(p, l, r);
  if (ll <= mid) update(l, mid, ll, rr, ls(p), val);
  if (rr > mid) update(mid + 1, r, ll, rr, rs(p), val);
  pushup(p);
}
node query(int l, int r, int ll, int rr, int p) {
  if (ll <= l && r <= rr) return tree[p];
  node ans;
  int mid = (l + r) >> 1;
  pushdown(p, l, r);
  if (ll <= mid) ans = ans + query(l, mid, ll, rr, ls(p));
  if (rr > mid) ans = ans + query(mid + 1, r, ll, rr, rs(p));
  return ans;
}
int main() {
  n = read(), m = read(), P = read();
  P = 100 / P;
  for (int i = 1; i <= n; i++) a[i] = read();
  build(1, n, 1);
  for (int i = 1; i <= m; i++) {
    int opt;
    opt = read();
    if (opt == 1) {
      int l, r, id;
      l = read(), r = read(), id = read();
      update(1, n, l, r, 1, id);
    } else {
      int l, r;
      l = read(), r = read();
      node ans = query(1, n, l, r, 1);
      printf("%d", (int)ans.size());
      for (int i = 0; i < ans.size(); i++) printf(" %d", ans.V[i]);
      puts("");
    }
  }
}
