#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <math.h>
#include <string>
#include <numeric>
#include <queue>
#include <cstdio>
#include <cstring>
#define ll long long
#define rep(i,n) for(ll i=0;i<n;++i)
#define rep1(i,n) for(ll i=1;i<n;++i)
#define mrep(i,n) for(ll i=n;i>=0;--i)
#define all(a) (a).begin(),(a).end()
#define vl vector<ll>
#define vvl vector<vector<ll> >
#define vb vector<bool>
#define vvb vector<vector<bool> >
#define pl pair<ll,ll>
#define inf 1001001001001001000
//#define mod 1000000007
#define mod 998244353
#define pi 3.1415926535
using namespace std;
struct __INIT {
	__INIT() {
		cin.tie(0);
		ios::sync_with_stdio(false);
		cout << fixed << setprecision(15);
	}
}__init;

vl a,b,c;

class ngo{
public:
    ll p1,p2,p3;
    ngo():p1(-1),p2(-1),p3(-3){}
    ngo(ll t1,ll t2,ll t3):p1(t1),p2(t2),p3(t3){}
    bool operator < (ngo t){
        return score() < t.score();
    }
    bool operator==(ngo t){
        return (p1 == t.p1) && (p2 == t.p2) && (p3 == t.p3);
    }
    ll score(){
        return a[p1]+b[p2]+c[p3];
    }
};

template<typename T>
struct AvlTree {
    struct node {
    	node* left = NULL;
    	node* right = NULL;
    	node* parent = NULL;
    	ll height = 0;
    	ll size = 1;
    	ll dup = 1;
    	//first:value second:count
    	T value;
    	ll getLheight() { return (left == NULL) ? 0 : left->height; }
    	ll getRheight() { return (right == NULL) ? 0 : right->height; }
    	void setHeight() {
    		if (left == NULL && right == NULL) height = 0;
    		else height = max(getLheight(), getRheight()) + 1;
    	}
    	ll getLsize() { return (left == NULL) ? 0 : left->size; }
    	ll getRsize() { return (right == NULL) ? 0 : right->size; }
    	void setSize() { size = getLsize() + getRsize() + dup; }
    };
public:
	node *root;
	AvlTree() { root = NULL; }
	AvlTree(T r) {
		root = new node();
		root->value = r;
	}
	void insert(T x) {
		node* now = root;
		if (now == NULL) {
			root = new node();
			root->value = x;
			return;
		}
		while (1) {
			if (x < now->value) {
				if (now->left != NULL) now = now->left;
				else {
					now->left = new node();
					now->left->value = x;
					now->left->parent = now;
					break;
				}
			}
			else {
				if (now->right != NULL) now = now->right;
				else {
					now->right = new node();
					now->right->value = x;
					now->right->parent = now;
					break;
				}
			}
		}
		balance(now);
	}

	//最後の一つを消すことは想定してない
	//無い値は消せない
	void del(T x) {
		node* n = root;
		while (!(n->value == x)) {
			if (x < n->value) n = n->left;
			else n = n->right;
		}
		if (n->dup > 1) {
			n->dup--;
			while(n != NULL){
			    n->setSize();
			    n = n->parent;
			}
			return;
		}
		if (n->left != NULL) {
			node* kwr = n->left;
			while (kwr->right != NULL) kwr = kwr->right;
			n->value = kwr->value;
			n->dup = kwr->dup;
			if (n->left->value == kwr->value) {
				n->left = kwr->left;
				if (kwr->left != NULL) {
					kwr->left->parent = n;
				}
				kwr->parent = NULL;
				kwr->left = NULL;
				balance(n);
			}
			else {
				kwr->parent->right = kwr->left;
				if (kwr->left != NULL) {
					kwr->left->parent = kwr->parent;
				}
				balance(kwr->parent);
				kwr->parent = NULL;
				kwr->left = NULL;
			}
		}
		else if (n->right != NULL) {
			node* kwr = n->right;
			while (kwr->left != NULL) kwr = kwr->left;
			n->value = kwr->value;
			n->dup = kwr->dup;
			if (kwr->value == n->right->value) {
				n->right = kwr->right;
				if (kwr->right != NULL) {
					kwr->right->parent = n;
				}
				kwr->parent = NULL;
				kwr->right = NULL;
				balance(n);
			}
			else {
				kwr->parent->left = kwr->right;
				if (kwr->right != NULL) {
					kwr->right->parent = kwr->parent;
				}
				balance(kwr->parent);
				kwr->parent = NULL;
				kwr->right = NULL;
			}
		}
		else {
		    if(n->parent == NULL){
		        root = NULL;
		        return;
		    }
			if (n->parent->left != NULL && n->parent->left->value == n->value) {
				n->parent->left = NULL;
			}
			else {
				n->parent->right = NULL;
			}
			balance(n->parent);
		}
	}
	
	void delAll(T x){
	    node* n = root;
		while (!(n->value == x)) {
			if (x < n->value) n = n->left;
			else n = n->right;
		}
		if (n->dup > 1) {
			n->dup = 1;
			node* p = n;
			while(p != NULL){
			    p->setSize();
			    p = p->parent;
			}
		}

		if (n->left != NULL) {
			node* kwr = n->left;
			while (kwr->right != NULL) kwr = kwr->right;
			n->value = kwr->value;
			n->dup = kwr->dup;
			if (n->left->value == kwr->value) {
				n->left = kwr->left;
				if (kwr->left != NULL) {
					kwr->left->parent = n;
				}
				kwr->parent = NULL;
				kwr->left = NULL;
				balance(n);
			}
			else {
				kwr->parent->right = kwr->left;
				if (kwr->left != NULL) {
					kwr->left->parent = kwr->parent;
				}
				balance(kwr->parent);
				kwr->parent = NULL;
				kwr->left = NULL;
			}
		}
		else if (n->right != NULL) {
			node* kwr = n->right;
			while (kwr->left != NULL) kwr = kwr->left;
			n->value = kwr->value;
			n->dup = kwr->dup;
			if (kwr->value == n->right->value) {
				n->right = kwr->right;
				if (kwr->right != NULL) {
					kwr->right->parent = n;
				}
				kwr->parent = NULL;
				kwr->right = NULL;
				balance(n);
			}
			else {
				kwr->parent->left = kwr->right;
				if (kwr->right != NULL) {
					kwr->right->parent = kwr->parent;
				}
				balance(kwr->parent);
				kwr->parent = NULL;
				kwr->right = NULL;
			}
		}
		else {
		    if(n->parent == NULL){
		        root = NULL;
		        return;
		    }
			if (n->parent->left != NULL && n->parent->left->value == n->value) {
				n->parent->left = NULL;
			}
			else {
				n->parent->right = NULL;
			}
			balance(n->parent);
		}
	}

	void balance(node* n) {
		while (n != NULL) {
			n->setHeight();
			n->setSize();
			// rrotate chance
			if (n->getLheight() - 2 == n->getRheight()) {
				if (n->left->getLheight() - 1 == n->left->getRheight() || n->left->getLheight() == n->left->getRheight()) {
					rrotate(n);
				}
				else {
					lrotate(n->left);
					rrotate(n);
				}
			}
			if (n->getRheight() - 2 == n->getLheight()) {
				//cout<<"balance "<<n->value<<endl;
				if (n->right->getRheight() - 1 == n->right->getLheight() || n->right->getRheight() == n->right->getLheight()) {
					lrotate(n);
				}
				else {
					rrotate(n->right);
					lrotate(n);
				}
			}
			n = n->parent;
		}
	}

	void rrotate(node* n) {
		node* lnode = n->left;
		T v = n->value;
		ll d = n->dup;
		n->value = lnode->value;
		n->dup = lnode->dup;
		lnode->value = v;
		lnode->dup = d;
		n->left = lnode->left;
		if (lnode->left != NULL) {
			(lnode->left)->parent = n;
		}
		lnode->left = lnode->right;
		lnode->right = n->right;
		if (n->right != NULL) {
			(n->right)->parent = lnode;
		}
		n->right = lnode;
		lnode->setHeight();
		lnode->setSize();
		n->setHeight();
		n->setSize();
	}

	void lrotate(node* n) {
		node* rnode = n->right;
		T v = n->value;
		ll d = n->dup;
		n->value = rnode->value;
		n->dup = rnode->dup;
		rnode->value = v;
		rnode->dup = d;
		n->right = rnode->right;
		if (rnode->right != NULL) {
			rnode->right->parent = n;
		}
		rnode->right = rnode->left;
		rnode->left = n->left;
		if (n->left != NULL) {
			n->left->parent = rnode;
		}
		n->left = rnode;
		rnode->setHeight();
		rnode->setSize();
		n->setHeight();
		n->setSize();
	}

	T findMax() {
		node *n = root;
		//if (n == NULL) return -inf;
		while (n->right != NULL) n = n->right;
		return n->value;
	}

	T findMin() {
		node *n = root;
		//if (n == NULL) return inf;
		while (n->left != NULL) n = n->left;
		return n->value;
	}
	//k番目に小さい値
	//1-indexed
	T findKMin(ll k,node* n) {
	    //if(n == NULL) return inf;
		//if (k > n->size) return inf;
		if (k <= n->getLsize()) return findKMin(k, n->left);
		else if (k > n->size - n->getRsize()) return findKMin(k-(n->size-n->getRsize()), n->right);
		else return n->value;
	}
	
	bool find(T t){
	    node* n = root;
	    while(n != NULL && !(n->value == t)){
	        if(t < n->value) n = n->left;
	        else n = n->right;
	    }
	    return n != NULL;
	}
	
	ll getSize(){
	    if(root != NULL) return root->size;
	    else return 0;
	}

	void show(node *n) {
	    if(n == NULL) return;
		cout << n->value << " lh:" << n->getLheight() << " rh:" << n->getRheight() <<" ls:"<<n->getLsize() <<" rs:" << n->getRsize() <<" size:"<<n->size <<" dup:"<<n->dup<< endl;
		if (n->left == NULL && n->right == NULL) {
			cout << "leafe" << endl;
		}
		else {
			if (n->left != NULL) show(n->left);
			if (n->right != NULL) show(n->right);
		}
	}
};

int main(void) {
    ll x,y,z,k;
    cin>>x>>y>>z>>k;
    a = vl(x);
    b = vl(y);
    c = vl(z);
    rep(i,x) cin>>a[i];
    rep(i,y) cin>>b[i];
    rep(i,z) cin>>c[i];
    AvlTree<ngo> at;
    sort(all(a));
    sort(all(b));
    sort(all(c));
    at.insert(ngo(x-1,y-1,z-1));
    map<vl,bool> unchi;
    rep(i,k){
        ngo tmp = at.findMax();
        //at.show(at.root);
        cout<<tmp.score()<<endl;
        at.del(tmp);
        if(tmp.p1 > 0 && !unchi[{tmp.p1-1,tmp.p2,tmp.p3}]){
            at.insert(ngo(tmp.p1-1,tmp.p2,tmp.p3));
            unchi[{tmp.p1-1,tmp.p2,tmp.p3}] = true;
        }
        if(tmp.p2 > 0 && !unchi[{tmp.p1,tmp.p2-1,tmp.p3}]){
            at.insert(ngo(tmp.p1,tmp.p2-1,tmp.p3));
            unchi[{tmp.p1,tmp.p2-1,tmp.p3}] = true;
        }
        if(tmp.p3 > 0 && !unchi[{tmp.p1,tmp.p2,tmp.p3-1}]){
            at.insert(ngo(tmp.p1,tmp.p2,tmp.p3-1));
            unchi[{tmp.p1,tmp.p2,tmp.p3-1}] = true;
        }
    }
    return 0;
}


Measured memory_bytes: 4968