#include "bits/stdc++.h"
using namespace std;
#ifdef duc_debug
#include "bits/debug.h"
#else 
#define debug(...)          
#endif
#define int long long
const int maxn = 1e6 + 6;
const int inf = 1e18;
const int lg = 21;
int up[maxn][lg + 1];
int n, a[maxn], f[maxn];
int best[maxn];
namespace mmb{
    const int N = 3003;
    int g[N];
    void solve(){
        for(int i = 1; i <= n; ++i){
            int mx = a[i];
            f[i] = g[i] = inf;
            for(int j = i; j; --j){
                mx = max(mx, a[j]);
                int cur = f[j - 1] + mx * (n - j + 1);
                f[i] = min(f[i], cur);
            }
        }
        cout << f[n];
    }
}
bool sub3_valid_input(){
    for(int i = 2; i <= n; ++i){
        if(a[i] > a[i - 1]) return 0;
    }
    return 1;
}
int get(int l, int r){
    int p = 31 - __builtin_clz(r - l + 1);
    return max(up[l][p], up[r - (1 << p) + 1][p]);
}
struct Line {
  mutable long long m, b, p;
  bool operator<(const Line& o) const { return m < o.m; }
  bool operator<(long long x) const { return p < x; }
};
struct LineContainer : multiset<Line, less<>> {
  // (for doubles, use inf = 1/.0, div(a,b) = a/b)
  const long long inf = LLONG_MAX;
  long long div(long long a, long long b) { // floored division
    return a / b - ((a ^ b) < 0 && a % b); 
  }
  bool isect(iterator x, iterator y) {
    if (y == end()) { x->p = inf; return false; }
    if (x->m == y->m) x->p = x->b > y->b ? inf : -inf;
    else x->p = div(y->b - x->b, x->m - y->m);
    return x->p >= y->p;
  }
  void add(long long m, long long b) {
    auto z = insert({m, b, 0}), y = z++, x = y;
    while (isect(y, z)) z = erase(z);
    if (x != begin() && isect(--x, y)) isect(x, y = erase(y));
    while ((y = x) != begin() && (--x)->p >= y->p) isect(x, erase(y));
  }
  long long query(long long x) {
    assert(!empty());
    auto l = *lower_bound(x);
    return l.m * x + l.b;
  }
};
void solve(){
    cin >> n;
    for(int i = 1; i <= n; ++i){
        cin >> a[i];
        up[i][0] = a[i];
    }
    for(int i = 1; i <= lg; ++i){
        for(int j = 1; j + (1 << i) <= n + 1; ++j){
            up[j][i] = max(up[j][i - 1], up[j + (1 << (i - 1))][i - 1]);
        }
    }
//    if(n <= 3000){
//        mmb::solve();
//        return;
//    }
//    if(sub3_valid_input()){
//        cout << a[1] * n;
//        return;
//    }
    LineContainer cht;
    cht.add(-n, 0);
    int cur = 0;
    for(int i = 1; i <= n; ++i){
        if(a[cur] < a[i]){
            while(cur < i){
                cht.add(cur - n, -f[cur]);
                ++cur;
            }
        }
        f[i] = -cht.query(a[cur]);
        debug(i, f[i], -cht.query(a[cur]));
    }
    cout << f[n];
}
signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    solve();
    
    return 0;
}
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... |