Submission #1171671

#TimeUsernameProblemLanguageResultExecution timeMemory
1171671fryingducDischarging (NOI20_discharging)C++20
100 / 100
335 ms188312 KiB
#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 timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...