#include <stdio.h>
#include <queue>
#include <vector>
#include <set>
using namespace std;
#define NMAX 50100
long long ta[NMAX], tb[NMAX], nat[NMAX];
vector<long long> r, tfin, raux;
priority_queue<pair<long long, int> > pq, pq2;
set<pair<long long, int> > next_avail_time, next_fin_time;
int i, Nra, Nrb, N, next_proc;
long long tcur, next_finish_time, resa, resb;
long long solveA() {
pair<long long, int> p;
for (i = 1; i <= Nra; i++)
pq.push(make_pair(-ta[i], i));
while (N--) {
p = pq.top();
r.push_back(-p.first);
pq.pop();
//fprintf(stderr, "Job %d A: processor=%d, starts at time=%d, ends at time=%d\n", r.size(), p.second, (int) ((-p.first) - ta[p.second]), (int) (-p.first));
pq.push(make_pair(-(-p.first + ta[p.second]), p.second));
}
N = r.size();
return r[N - 1];
}
long long solveB() {
set<pair<long long, int> >::iterator it;
pair<long long, int> p;
int sel_type;
// Initialize everything.
while (pq.size() > 0)
pq.pop();
next_avail_time.clear();
tcur = 0;
for (i = 1; i <= Nrb; i++) {
nat[i] = 0;
next_avail_time.insert(make_pair(nat[i], i));
pq.push(make_pair(-tb[i], i));
}
// Process the type B jobs.
N = r.size();
for (i = 0; i < N; i++) {
if (r[i] > tcur) {
p.first = tcur + 1;
p.second = 0;
it = next_avail_time.lower_bound(p);
tcur = r[i];
while (1) {
if (it == next_avail_time.end())
break;
//fprintf(, "old_tcur=%d, new_tcur=%d, (*it).first=%d, (*it).second=%d\n", p.first - 1, tcur, (*it).first, (*it).second);
if ((*it).first > tcur)
break;
pq.push(make_pair(-tb[(*it).second], (*it).second));
it++;
}
}
next_proc = next_finish_time = 0;
while (pq.size() > 0) {
p = pq.top();
if (nat[p.second] <= tcur) {
next_proc = p.second;
next_finish_time = tcur + (-p.first);
break;
} else {
pq.pop();
}
}
while (pq2.size() > 0) {
p = pq2.top();
if ((nat[p.second] > tcur) && (nat[p.second] + tb[p.second] == (-p.first))) {
if (((-p.first) < next_finish_time) || (!next_proc)) {
next_proc = p.second;
next_finish_time = -p.first;
}
break;
} else {
pq2.pop();
}
}
if (nat[next_proc] <= tcur) {
pq.pop();
sel_type = 1;
} else {
pq2.pop();
sel_type = 2;
}
tfin.push_back(next_finish_time);
//fprintf(stderr, "Job %d B: processor=%d (sel_type=%d), starts at time=%d (avail=%d), ends at time=%d, duration=%d\n", tfin.size(), next_proc, sel_type, (int) (nat[next_proc] > tcur ? nat[next_proc] : tcur), (int) r[i], (int) next_finish_time, (int) tb[next_proc]);
next_avail_time.erase(make_pair(nat[next_proc], next_proc));
nat[next_proc] = next_finish_time;
next_avail_time.insert(make_pair(nat[next_proc], next_proc));
if (nat[next_proc] <= tcur) {
pq.push(make_pair(-tb[next_proc], next_proc));
} else {
pq2.push(make_pair(-(nat[next_proc] + tb[next_proc]), next_proc));
}
}
return tfin[tfin.size() - 1];
}
char checkSol(long long T) {
pair<long long, int> p;
raux.clear();
for (i = 0; i < N; i++)
raux.push_back(T - r[i]);
while (pq.size() > 0)
pq.pop();
for (i = 1; i <= Nrb; i++)
pq.push(make_pair(-tb[i], i));
for (i = N - 1; i >= 0; i--) {
p = pq.top();
if ((-p.first) > raux[i])
return 0;
pq.pop();
// fprintf(stderr, "Job %d B: processor=%d, starts at time=%d, ends at time=%d\n", r.size(), p.second, (int) ((-p.first) - ta[p.second]), (int) (-p.first));
pq.push(make_pair(-(-p.first + tb[p.second]), p.second));
}
return 1;
}
long long solveBbetter() {
long long li = resa, ls = resa + tb[1] * N, mid, Tok = ls;
while (li <= ls) {
mid = (li + ls) / 2;
// Check if all the jobs can be scheduled on the type B processors within time mid.
if (checkSol(mid)) {
Tok = mid;
ls = mid - 1;
} else {
li = mid + 1;
}
}
return Tok;
}
int main() {
// Read the input data.
freopen("fabrica.in", "r", stdin);
scanf("%d %d %d", &N, &Nra, &Nrb);
for (i = 1; i <= Nra; i++)
scanf("%lld", &ta[i]);
for (i = 1; i <= Nrb; i++)
scanf("%lld", &tb[i]);
// Solve A.
resa = solveA();
// Solve B.
resb = solveBbetter();
// Write the output data.
freopen("fabrica.out", "w", stdout);
printf("%d %d\n", (int) resa, (int) resb);
return 0;
}