#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... |