This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/courses/library/7/DPL/3/DPL_3_C"
#include "../../Src/Template/IOSetting.hpp"
#include "../../Src/Sequence/CartesianTree.hpp"
#include <algorithm>
#include <iostream>
#include <vector>
using namespace zawa;
int main() {
SetFastIO();
int N;
std::cin >> N;
std::vector<int> H(N);
for (auto& h : H) std::cin >> h;
using Tree = CartesianTree<int>;
Tree T{H, [](int l, int r) { return l < r; }};
long long ans{};
std::vector<int> size(N);
T.treeDP([&](const Tree::Node& node) {
auto v{node.idx};
size[v] = 1;
if (node.left != Tree::Invalid) size[v] += size[node.left];
if (node.right != Tree::Invalid) size[v] += size[node.right];
ans = std::max(ans, (long long)size[v] * node.value);
});
std::cout << ans << '\n';
}
#line 1 "Test/AOJ/DPL_3_C.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/courses/library/7/DPL/3/DPL_3_C"
#line 2 "Src/Template/IOSetting.hpp"
#line 2 "Src/Template/TypeAlias.hpp"
#include <cstdint>
#include <cstddef>
namespace zawa {
using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128_t;
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using usize = std::size_t;
} // namespace zawa
#line 4 "Src/Template/IOSetting.hpp"
#include <iostream>
#include <iomanip>
namespace zawa {
void SetFastIO() {
std::cin.tie(nullptr)->sync_with_stdio(false);
}
void SetPrecision(u32 dig) {
std::cout << std::fixed << std::setprecision(dig);
}
} // namespace zawa
#line 2 "Src/Sequence/CartesianTree.hpp"
#line 4 "Src/Sequence/CartesianTree.hpp"
#include <concepts>
#include <cassert>
#include <type_traits>
#include <vector>
namespace zawa {
template <class T>
class CartesianTree {
public:
static constexpr usize Invalid{static_cast<usize>(-1)};
struct Node {
usize left{Invalid}, right{Invalid}, par{Invalid}, idx{Invalid};
T value{};
std::vector<usize> childs() const noexcept {
std::vector<usize> res;
res.reserve(2);
if (left != Invalid) res.push_back(left);
if (right != Invalid) res.push_back(right);
return res;
}
usize countChilds() const noexcept {
return (left != Invalid) + (right != Invalid);
}
};
CartesianTree() = default;
template <class F>
requires std::strict_weak_order<F, T, T>
CartesianTree(const std::vector<T>& A, F comp)
: m_size{A.size()}, m_nodes(A.size()) {
std::vector<usize> stack(A.size());
usize top{};
for (usize i{} ; i < size() ; i++) {
if (top and comp(A[i], A[stack[top - 1]])) {
while (top and comp(A[i], A[stack[top - 1]])) top--;
m_nodes[i].left = stack[top];
m_nodes[stack[top]].par = i;
}
if (top) {
m_nodes[i].par = stack[top - 1];
m_nodes[stack[top - 1]].right = i;
}
else {
m_root = i;
}
m_nodes[i].value = A[i];
m_nodes[i].idx = i;
stack[top++] = i;
}
}
inline usize size() const noexcept {
return m_size;
}
inline usize root() const noexcept {
return m_root;
}
inline T value(usize i) const noexcept {
assert(i < size());
return m_nodes[i].value;
}
inline usize parent(usize i) const noexcept {
assert(i < size());
return m_nodes[i].par;
}
inline usize left(usize i) const noexcept {
assert(i < size());
return m_nodes[i].left;
}
inline usize right(usize i) const noexcept {
assert(i < size());
return m_nodes[i].right;
}
template <class F>
void treeDP(F func) {
static_assert(std::is_invocable_v<F, const Node&>, "F must be invocable f(const Node&)");
dfs(m_root, func);
}
private:
template <class F>
void dfs(usize v, F func) {
if (m_nodes[v].left != Invalid) dfs(m_nodes[v].left, func);
if (m_nodes[v].right != Invalid) dfs(m_nodes[v].right, func);
func(m_nodes[v]);
}
usize m_size{}, m_root{Invalid};
std::vector<Node> m_nodes;
};
} // namespace zawa
#line 5 "Test/AOJ/DPL_3_C.test.cpp"
#include <algorithm>
#line 9 "Test/AOJ/DPL_3_C.test.cpp"
using namespace zawa;
int main() {
SetFastIO();
int N;
std::cin >> N;
std::vector<int> H(N);
for (auto& h : H) std::cin >> h;
using Tree = CartesianTree<int>;
Tree T{H, [](int l, int r) { return l < r; }};
long long ans{};
std::vector<int> size(N);
T.treeDP([&](const Tree::Node& node) {
auto v{node.idx};
size[v] = 1;
if (node.left != Tree::Invalid) size[v] += size[node.left];
if (node.right != Tree::Invalid) size[v] += size[node.right];
ans = std::max(ans, (long long)size[v] * node.value);
});
std::cout << ans << '\n';
}