// Original C++ solution (slower):
// #include <bits/stdc++.h>

#include <cstdio>

#include <vector>

#include <functional>

#include <algorithm>

#include <queue>

#include <set>

using namespace std;



using i32 = int;

using i64 = long long;



#define REP(i, stop) FOR(i, 0, stop)

#define FOR(i, start, stop) for (int i = start, i##_len = stop; i < i##_len; ++i)

#define RREP(i, n) for (int i = n; i-- > 0;)

#define ALL(v) (v).begin(), (v).end()



template<typename T>

T read() {

  T a = 0;

  for(;;) {

    char c = getchar();

    if ('0' <= c && c <= '9') {

      a = a * 10 + c - 48;

    } else {

      return a;

    }

  }

}



signed main() {

//  i32 x, y, z, k;

//  scanf("%d%d%d%d", &x, &y, &z, &k);

  i32 x = read<i32>(),

      y = read<i32>(),

      z = read<i32>(),

      k = read<i32>();

  vector<i64> A(x), B(y), C(z);

//  REP(i, x) scanf("%lld", &A[i]);

//  REP(i, y) scanf("%lld", &B[i]);

//  REP(i, z) scanf("%lld", &C[i]);

  REP(i, x) A[i] = read<i64>();

  REP(i, y) B[i] = read<i64>();

  REP(i, z) C[i] = read<i64>();

  sort(ALL(A), greater<i64>());

  sort(ALL(B), greater<i64>());

  sort(ALL(C), greater<i64>());

  using P = pair<i64, i64>;

  priority_queue<P> Q;

  Q.push({A[0] + B[0] + C[0], 0});

  set<i64> S;

  S.insert(0);

  REP(_, k) {

    i64 p = Q.top().first;

    i64 q = Q.top().second;

    Q.pop();

    printf("%lld\n", p);

    i32 u = q & 1023;

    i32 v = q >> 10 & 1023;

    i32 w = q >> 20 & 1023;

    i64 u1 = q + 1;

    i64 v1 = q + (1 << 10);

    i64 w1 = q + (1 << 20);

    if (u + 1 < x && !S.count(u1)) { S.insert(u1); Q.push({A[u + 1] + B[v] + C[w], u1}); }

    if (v + 1 < y && !S.count(v1)) { S.insert(v1); Q.push({A[u] + B[v + 1] + C[w], v1}); }

    if (w + 1 < z && !S.count(w1)) { S.insert(w1); Q.push({A[u] + B[v] + C[w + 1], w1}); }

  }

}

// Optimized solution to the same problem (faster):
#include <cstdio>

#include <algorithm>

#include <functional>

#include <set>

using namespace std;



using i32 = int;

using i64 = long long;



#define REP(i, stop) for (register int i = 0; i < stop; ++i)



template<typename T>

T read() {

  T a = 0;

  register int c;

  for(;;) {

    c = getchar_unlocked();

    if (c & 16) {

      a = a * 10 + c - 48;

    } else {

      return a;

    }

  }

}



void writeln(i64 a) {

  char buf[20];

  register int i = 0;

  // if (a <= 0)

  while (a > 0) {

    buf[i++] = a % 10;

    a = a / 10;

  }

  while (i > 0) {

    putchar_unlocked(buf[--i] + 48);

  }

  putchar_unlocked('\n');

}



i64 A[1000], B[1000], C[1000];

i64 ABC[3000];

signed main() {

  i32 X = read<i32>(),

      Y = read<i32>(),

      Z = read<i32>(),

      K = read<i32>();

  REP(i, X) A[i] = read<i64>();

  REP(i, Y) B[i] = read<i64>();

  REP(i, Z) C[i] = read<i64>();

  sort(A, A + X, greater<i64>());

  sort(B, B + Y, greater<i64>());

  sort(C, C + Z, greater<i64>());

  i64 A0 = A[0],

      B0 = B[0],

      C0 = C[0];

  REP(i, X) A[i] = A0 - A[i];

  REP(i, Y) B[i] = B0 - B[i];

  REP(i, Z) C[i] = C0 - C[i];

  i64 l = 0,

      r = A0 + B0 + C0,

      m;

  while (l < r) {

    m = (l + r) / 2;

    i32 cnt = 0;

    REP(i, X) {

      if (A[i] > m) break;

      REP(j, Y) {

        if (A[i] + B[j] > m) break;

        REP(k, Z) {

          if (A[i] + B[j] + C[k] > m) break;

          ++cnt;

          if (cnt >= K) {

            r = m;

            goto NEXT;

          }

        }

      }

    }

    l = m + 1;

    NEXT:;

  }

  i32 c = 0;

  REP(i, X) {

    if (A[i] >= l) break;

    REP(j, Y) {

      if (A[i] + B[j] >= l) break;

      REP(k, Z) {

        if (A[i] + B[j] + C[k] >= l) break;

        ABC[c++] = A[i] + B[j] + C[k];

      }

    }

  }

  sort(ABC, ABC + c);

  REP(i, c) {

    writeln(A0 + B0 + C0 - ABC[i]);

  }

  REP(_, K - c) {

    writeln(A0 + B0 + C0 - l);

  }

}

// Fastest known solution for this problem: