#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using P = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;
const double eps = 1e-10;
const ll MOD = 1000000007;
const int INF = 1000000;
const ll LINF = 1ll << 50;
template <typename T>
void printv(const vector<T>& s) {
  for (int i = 0; i < (int)(s.size()); ++i) {
    cout << s[i];
    if (i == (int)(s.size()) - 1)
      cout << endl;
    else
      cout << " ";
  }
}
template <typename T1, typename T2>
ostream& operator<<(ostream& os, const pair<T1, T2> p) {
  os << p.first << ":" << p.second;
  return os;
}
struct XorShift {
  uint32_t w, x, y, z;
  XorShift(uint32_t seed = time(nullptr)) {
    w = seed;
    x = w << 13;
    y = (w >> 9) ^ (x << 6);
    z = y >> 7;
  }
  uint32_t rand() {
    uint32_t t = x ^ (x << 11);
    x = y;
    y = z;
    z = w;
    return w = (w ^ (w >> 19) ^ (t ^ (t >> 8)));
  }
  int randInt(int min = 0, int max = 0x7FFFFFFF) {
    return rand() % (max - min + 1) + min;
  }
  double randDouble(double min = 0, double max = 1) {
    return (double)(rand() % 0xFFFF) / 0xFFFF * (max - min) + min;
  }
  void SetDefault() {
    w = 123456789;
    x = 362436069;
    y = 521288629;
    z = 88675123;
  }
};
XorShift randgen;
int n, w, k, v;
vector<int> col, val;
struct STATE {
  vector<int> pos;
  vvi num;
  STATE() {
    pos.resize(n);
    num.resize(w);
  }
};
void init(STATE& state) {
  for (int i = 0; i < n; ++i) {
    state.pos[i] = i % w;
    state.num[i % w].push_back(i);
  }
}
void update(STATE& state) {
  int num1 = 0, num2 = 0;
  while (state.pos[num1] == state.pos[num2]) {
    num1 = randgen.randInt(0, n - 1);
    num2 = randgen.randInt(0, n - 1);
  }
  auto it1 = find(state.num[state.pos[num1]].begin(),
                  state.num[state.pos[num1]].end(), num1);
  auto it2 = find(state.num[state.pos[num2]].begin(),
                  state.num[state.pos[num2]].end(), num2);
  state.num[state.pos[num1]].erase(it1);
  state.num[state.pos[num2]].erase(it2);
  auto it3 = upper_bound(state.num[state.pos[num1]].begin(),
                         state.num[state.pos[num1]].end(), num2);
  auto it4 = upper_bound(state.num[state.pos[num2]].begin(),
                         state.num[state.pos[num2]].end(), num1);
  state.num[state.pos[num1]].insert(it3, num2);
  state.num[state.pos[num2]].insert(it4, num1);
  swap(state.pos[num1], state.pos[num2]);
  return;
}
int score(STATE& state) {
  int minh = n / w;
  int res = 0;
  for (int i = 0; i < minh; ++i) {
    vi point(k);
    for (int j = 0; j < w; ++j) {
      point[col[state.num[j][i]]] += val[state.num[j][i]];
    }
    int ma = 0;
    for (int j = 0; j < (int)(point.size()); ++j) {
      ma = max(ma, point[j]);
    }
    res += ma;
  }
  return res;
}
int nowscore = 0;
void sa() {
  const double TIME_LIMIT = 1.95;
  STATE state;
  init(state);
  nowscore = score(state);
  double start_temp = 50, end_temp = 10;
  double start_time = clock();
  int cnt = 0;
  while (true) {
    double now_time = clock();
    if (cnt % 10000 == 0 &&
        (double)(now_time - start_time) / CLOCKS_PER_SEC > TIME_LIMIT)
      break;
    STATE new_state = state;
    update(new_state);
    int new_score = score(new_state);
    if (new_score > nowscore) {
      state = new_state;
      nowscore = new_score;
    }
  }
  for (int i = 0; i < n; ++i) {
    cout << state.pos[i] << endl;
  }
}
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(10);
  cin >> n >> w >> k >> v;
  col.resize(n);
  val.resize(n);
  for (int i = 0; i < n; ++i) {
    cin >> col[i] >> val[i];
  }
  sa();
}
