Разбор
Сначала вычислим объем воды в контейнере между крайними верткальными линиями, то есть между линиями пары . Затем будем двигать указатели и навстречу друг другу:
если , то увеличим на ;
если , то уменьшим на ;
Объем воды между линиями и равен . Среди всех полученных значений находим наибольшее.
Задачу можно решить за . Однако из-за ограничения такое решение приведёт к превышению лимита времени (Time Limit). Достаточно перебрать пары линий , для которых , и далее для каждой такой пары вычислить объем воды, который они могут удерживать. Среди всех вычисленных значений находим максимальный объём.
Пример
Контейнер из первого теста имеет вид:
Наибольшее количество воды можно удержать между линиями и . Высота уровня воды составит , а объем воды равен .
Реализация алгоритма
Читаем входные данные.
scanf("%d", &n); h.resize(n); for (i = 0; i < n; i++) scanf("%lld", &h[i]);
В переменной будем хранить максимальное количество воды, которое может удерживать контейнер.
long long res = 0;
Инициализируем пару указателей .
int l = 0, r = h.size() - 1;
Двигаем указатели и навстречу друг другу, пока они не встретятся.
while (l < r) {
Объем воды между линиями и равен . Среди всех таких объемов находим максимальный.
res = max(res, min(h[l], h[r]) * (r - l));
Перемещаем указатели.
if (h[l] < h[r]) l += 1; else r -= 1; }
Выводим ответ.
printf("%lld\n", res);
Реализация алгоритма — O(n^2), Time Limit
Читаем входные данные.
scanf("%d", &n); v.resize(n); for (i = 0; i < n; i++) scanf("%lld", &v[i]);
В переменной будем хранить максимальное количество воды, которое может удерживать контейнер.
long long res = 0;
Перебираем все возможные пары линий .
for (i = 0; i < n; i++) for (j = i + 1; j < n; j++)
Объем воды между линиями и равен . Среди всех таких объемов находим максимальный.
res = max(res, min(v[i], v[j]) * (j - i));
Выводим ответ.
printf("%lld\n", res);