Problem p03078 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <array>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <thread>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#define FOR_LT(i, beg, end) for (int i = beg; i < end; i++)
#define FOR_LE(i, beg, end) for (int i = beg; i <= end; i++)

using namespace std;

int count_upper(uint64_t v, vector<uint64_t> &as, vector<uint64_t> &bs,
                vector<uint64_t> &cs, int x, int y, int z, int k) {
  int count = 0;

  multiset<uint64_t> vals;
  FOR_LT(a, 0, x) {
    if (v <= as[a]) {
      count += y * z;
      continue;
    }

    FOR_LT(b, 0, y) {
      if (v <= as[a] + bs[b]) {
        count += z;
        continue;
      }

      FOR_LT(c, 0, z) {
        if (as[a] + bs[b] + cs[c] < v)
          break;

        count++;
        if (k < count)
          return count;
      }
    }
  }

  return count;
}

int main() {
  int x, y, z, k;
  cin >> x >> y >> z >> k;

  vector<uint64_t> as(x);
  vector<uint64_t> bs(y);
  vector<uint64_t> cs(z);
  for (auto &a : as) {
    cin >> a;
  }
  for (auto &b : bs) {
    cin >> b;
  }
  for (auto &c : cs) {
    cin >> c;
  }

  sort(as.begin(), as.end(), greater<uint64_t>());
  sort(bs.begin(), bs.end(), greater<uint64_t>());
  sort(cs.begin(), cs.end(), greater<uint64_t>());

  uint64_t h = as.front() + bs.front() + cs.front();
  uint64_t l = as.back() + bs.back() + cs.back();
  uint64_t h_n = 1;
  uint64_t l_n = x * y * z;

  while (true) {
    if (l == h)
      break;
    uint64_t m = (h + l) / 2;

    int count = count_upper(m, as, bs, cs, x, y, z, k);
    if (count == k) {
      h = l = m;
    } else if (count < k) {
      h = max(m - 1, l);
    } else {
      l = m;
    }
  }

  vector<uint64_t> vals;
  FOR_LT(a, 0, x) {
    FOR_LT(b, 0, y) {
      FOR_LT(c, 0, z) {
        if (as[a] + bs[b] + cs[c] < l)
          break;

        vals.push_back(as[a] + bs[b] + cs[c]);
      }
    }
  }

  sort(vals.begin(), vals.end());

  int count = 0;
  for (auto it = vals.rbegin(); it != vals.rend(); it++) {
    cout << *it << endl;
    count++;
    if (count == k)
      break;
  }

  return 0;
}

Fixed submission:
#include <algorithm>
#include <array>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <thread>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#define FOR_LT(i, beg, end) for (int i = beg; i < end; i++)
#define FOR_LE(i, beg, end) for (int i = beg; i <= end; i++)

using namespace std;

int count_upper(uint64_t v, vector<uint64_t> &as, vector<uint64_t> &bs,
                vector<uint64_t> &cs, int x, int y, int z, int k) {
  int count = 0;

  multiset<uint64_t> vals;
  FOR_LT(a, 0, x) {
    if (v <= as[a]) {
      count += y * z;
      continue;
    }

    FOR_LT(b, 0, y) {
      if (v <= as[a] + bs[b]) {
        count += z;
        continue;
      }

      FOR_LT(c, 0, z) {
        if (as[a] + bs[b] + cs[c] < v)
          break;

        count++;
        if (k < count)
          return count;
      }
    }
  }

  return count;
}

int main() {
  int x, y, z, k;
  cin >> x >> y >> z >> k;

  vector<uint64_t> as(x);
  vector<uint64_t> bs(y);
  vector<uint64_t> cs(z);
  for (auto &a : as) {
    cin >> a;
  }
  for (auto &b : bs) {
    cin >> b;
  }
  for (auto &c : cs) {
    cin >> c;
  }

  sort(as.begin(), as.end(), greater<uint64_t>());
  sort(bs.begin(), bs.end(), greater<uint64_t>());
  sort(cs.begin(), cs.end(), greater<uint64_t>());

  uint64_t h = as.front() + bs.front() + cs.front();
  uint64_t l = as.back() + bs.back() + cs.back();
  uint64_t h_n = 1;
  uint64_t l_n = x * y * z;

  while (true) {
    if (l == h)
      break;
    uint64_t m = (h + l) / 2;

    int count = count_upper(m, as, bs, cs, x, y, z, k);
    if (count == k) {
      h = l = m;
    } else if (count < k) {
      h = max(m - 1, l);
    } else {
      l = m;
      if (h - l == 1) {
        h = l;
        break;
      }
    }
  }

  vector<uint64_t> vals;
  FOR_LT(a, 0, x) {
    FOR_LT(b, 0, y) {
      FOR_LT(c, 0, z) {
        if (as[a] + bs[b] + cs[c] < l)
          break;

        vals.push_back(as[a] + bs[b] + cs[c]);
      }
    }
  }

  sort(vals.begin(), vals.end());

  int count = 0;
  for (auto it = vals.rbegin(); it != vals.rend(); it++) {
    cout << *it << endl;
    count++;
    if (count == k)
      break;
  }

  return 0;
}