/*
 * 演算法 / Algorithm:
 * 第一個設施貪心地取「最早結束」者；第二個設施開始於
 * max(第一個結束時間, 第二個開放時間)。兩種順序各算一次取最小。
 * Greedily fix the first ride as the earliest-finishing one; the second
 * starts at max(first finish, its open time). Try both orders, take the min.
 */
#include <vector>
#include <algorithm>   // 提供 std::min / std::max / provides std::min, std::max
using namespace std;

class Solution {
public:
    int earliestFinishTime(vector<int>& landStartTime, vector<int>& landDuration,
                           vector<int>& waterStartTime, vector<int>& waterDuration) {
        // lambda：傳入 start、duration 兩個陣列，回傳「最早結束時間」
        // a lambda (inline function) returning the earliest start+duration over a category
        auto earliestFinish = [](const vector<int>& start, const vector<int>& dur) {
            int best = start[0] + dur[0];                  // 用第 0 個當初始 / seed with index 0
            for (size_t k = 1; k < start.size(); k++)      // size_t 是無號整數，常用於索引 / unsigned index type
                best = min(best, start[k] + dur[k]);       // std::min 取較小者 / keep the smallest
            return best;
        };

        int minLandFinish  = earliestFinish(landStartTime,  landDuration);   // 陸上最早結束 / earliest land finish
        int minWaterFinish = earliestFinish(waterStartTime, waterDuration);  // 水上最早結束 / earliest water finish

        int best = INT_MAX;   // 先設成極大值，方便後面取 min / start at "infinity" so any real value wins

        // 順序一：先陸後水 / order 1: land then water
        for (size_t j = 0; j < waterStartTime.size(); j++) {
            // 第二個設施真正開始時間 = max(已玩完第一個的時間, 它的開放時間)
            // the second ride actually starts at max(first-finish, its own open time)
            int finish = max(minLandFinish, waterStartTime[j]) + waterDuration[j];
            best = min(best, finish);                       // 更新全域最小 / update the running minimum
        }

        // 順序二：先水後陸 / order 2: water then land
        for (size_t i = 0; i < landStartTime.size(); i++) {
            int finish = max(minWaterFinish, landStartTime[i]) + landDuration[i];
            best = min(best, finish);
        }

        return best;   // 最早完成兩個設施的時間 / earliest time to finish both
    }
};
