#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <algorithm>
#include <utility>
#include <functional>
#include <cstring>
#include <queue>
#include <stack>
#include <math.h>
#include <iterator>
#include <vector>
#include <string>
#include <set>
#include <math.h>
#include <iostream>
#include <random>
#include <map>
#include <fstream>
#include <iomanip>
#include <time.h>
#include <stdlib.h>
#include <list>
#include <typeinfo>
#include <list>
#include <set>
#include <assert.h>
#include <complex>
#include <omp.h>
using namespace std;
#define eps 0.000001
#define LONG_INF 10000000000000
#define GOLD 1.61803398874989484820458
#define seg_size 65536*4
#define REP(i,n) for(long long i = 0;i < n;++i)
unsigned long xor128() {
	static unsigned long x = time(NULL), y = 362436069, z = 521288629, w = 88675123;
	unsigned long t = (x ^ (x << 11));
	x = y; y = z; z = w;
	return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)));
}



void solve(long long X, long long Y, long long Z, long long K, std::vector<long long> A, std::vector<long long> B, std::vector<long long> C){
    sort(A.begin(),A.end(),greater<long long>());
    sort(B.begin(),B.end(),greater<long long>());
    sort(C.begin(),C.end(),greater<long long>());
    priority_queue<tuple<long long,int,int,int>> next;
    next.push(make_tuple(A[0]+B[0]+C[0],0,0,0));
    set<tuple<int,int,int>> kaburi;
    kaburi.insert(make_tuple(0,0,0));
    while(true){
        tuple<long long,int,int,int> now = next.top();
        next.pop();
        K--;
        cout << get<0>(now) << endl;
        if(K == 0){
            return;
        }
        if(get<1>(now) != X-1&&kaburi.find(make_tuple(get<1>(now)+1,get<2>(now),get<3>(now))) == kaburi.end()){
            get<1>(now)++;
                        kaburi.insert(make_tuple(get<1>(now),get<2>(now),get<3>(now)));
            get<0>(now) -= A[get<1>(now)-1];
            get<0>(now) += A[get<1>(now)];
            next.push(now);
            get<0>(now) += A[get<1>(now)-1];
            get<0>(now) -= A[get<1>(now)];
            get<1>(now)--;           
        }
        if(get<2>(now) != Y-1&&kaburi.find(make_tuple(get<1>(now),get<2>(now)+1,get<3>(now))) == kaburi.end()){
            get<2>(now)++;
            kaburi.insert(make_tuple(get<1>(now),get<2>(now),get<3>(now)));
            get<0>(now) -= B[get<2>(now)-1];
            get<0>(now) += B[get<2>(now)];
            next.push(now);
            get<0>(now) += B[get<2>(now)-1];
            get<0>(now) -= B[get<2>(now)];
            get<2>(now)--;  
        }
        if(get<3>(now) != Z-1&&kaburi.find(make_tuple(get<1>(now),get<2>(now),get<3>(now)+1)) == kaburi.end()){
            get<3>(now)++;
                        kaburi.insert(make_tuple(get<1>(now),get<2>(now),get<3>(now)));
            get<0>(now) -= C[get<3>(now)-1];
            get<0>(now) += C[get<3>(now)];
            next.push(now);
            get<0>(now) += C[get<3>(now)-1];
            get<0>(now) -= C[get<3>(now)];
            get<3>(now)--;  
        }
    }
}

// Generated by 1.1.3 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
int main(){
    long long X;
    scanf("%lld",&X);
    long long Y;
    scanf("%lld",&Y);
    long long Z;
    scanf("%lld",&Z);
    long long K;
    scanf("%lld",&K);
    std::vector<long long> A(X);
    for(int i = 0 ; i < X ; i++){
        scanf("%lld",&A[i]);
    }
    std::vector<long long> B(Y);
    for(int i = 0 ; i < Y ; i++){
        scanf("%lld",&B[i]);
    }
    std::vector<long long> C(Z);
    for(int i = 0 ; i < Z ; i++){
        scanf("%lld",&C[i]);
    }
    solve(X, Y, Z, K, std::move(A), std::move(B), std::move(C));
    return 0;
}


Measured memory_bytes: 896