Submission #879447

#TimeUsernameProblemLanguageResultExecution timeMemory
879447kh0iDischarging (NOI20_discharging)C++17
100 / 100
143 ms36580 KiB
#include "bits/stdc++.h" using namespace std; #ifdef LOCAL #include "debug.h" #else #define debug(...) #endif using ll = long long; using pii = pair<int, int>; #define F first #define S second #define sz(x) (int)((x).size()) #define all(x) (x).begin(), (x).end() mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()); ll get_rand(ll l, ll r) { assert(l <= r); return uniform_int_distribution<ll> (l, r)(rng); } const int N = 1e6 + 3; #pragma once struct Node{ ll val; const Node operator + (const Node &other){ Node res; res.val = max(val, other.val); return res; } }; struct ST{ int n; vector<Node> st; Node def = Node(); // default value void init(int _n){ n = _n; st.resize(4 * n + 6, def); } void _update(int id, int l, int r, int pos, ll val){ if(l == r){ st[id].val = val; return; } int m = (l + r) / 2; if(l <= pos and pos <= m) _update(2 * id, l, m, pos, val); else _update(2 * id + 1, m + 1, r, pos, val); st[id] = st[2 * id] + st[2 * id + 1]; } Node _query(int id, int l, int r, int tl, int tr){ if(l > tr or tl > r) return def; if(tl <= l and r <= tr) return st[id]; int m = (l + r) / 2; return _query(2 * id, l, m, tl, tr) + _query(2 * id + 1, m + 1, r, tl, tr); } Node query(int l, int r){ return _query(1, 1, n, l, r); } void update(int pos, ll val){ _update(1, 1, n, pos, val); } }; int n; ll a[N], f[N]; namespace Sub14{ bool valid_input(){ return n <= 1500; } void solve(){ ST dak; dak.init(n); for(int i = 1; i <= n; ++i) dak.update(i, a[i]); memset(f, 0x3f3f3f, sizeof(f)); f[0] = 0; for(int i = 1; i <= n; ++i) for(int j = 1; j <= i; ++j) f[i] = min(f[i], f[j - 1] + 1ll * (n - j + 1) * dak.query(j, i).val); cout << f[n]; } } struct Line { mutable ll k, m, p; bool operator<(const Line& o) const { return k < o.k; } bool operator<(ll x) const { return p < x; } }; struct LineContainer : multiset<Line, less<>> { // (for doubles, use inf = 1/.0, div(a,b) = a/b) static const ll inf = LLONG_MAX; ll div(ll a, ll b) { // floored division return a / b - ((a ^ b) < 0 && a % b); } bool isect(iterator x, iterator y) { if (y == end()) return x->p = inf, 0; if (x->k == y->k) x->p = x->m > y->m ? inf : -inf; else x->p = div(y->m - x->m, x->k - y->k); return x->p >= y->p; } void add(ll k, ll m) { auto z = insert({k, m, 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)); } ll query(ll x) { assert(!empty()); auto l = *lower_bound(x); return l.k * x + l.m; } }; namespace Sub2{ bool valid_input(){ bool ok = 1; for(int i = 2; i <= n; ++i) ok &= (a[i] >= a[i - 1]); return ok; } LineContainer cht; ll f[N]; void solve(){ f[0] = 1; cht.add(-n, 0); for(int i = 1; i <= n; ++i){ f[i] = -cht.query(a[i]); cht.add(-(n - i), -f[i]); } cout << f[n]; } } namespace Sub3{ bool valid_input(){ bool ok = 1; for(int i = n - 1; i >= 1; --i) ok &= (a[i] >= a[i + 1]); return ok; } ll pref[N]; void solve(){ f[0] = 0; pref[1] = f[0] + 1ll * n * a[1]; for(int i = 1; i <= n; ++i){ f[i] = pref[i]; pref[i + 1] = min(pref[i], f[i] + 1ll * (n - i) * a[i + 1]); } cout << f[n]; } } namespace Sub5{ int r[N]; ll mx[N]; LineContainer cht; void solve(){ int cur = 0; for(int i = 1; i <= n; ++i){ if(a[cur] < a[i]){ while(cur < i){ cht.add(-(n - cur), -f[cur]); ++cur; } } f[i] = -cht.query(a[cur]); } cout << f[n]; } } void solve(){ cin >> n; for(int i = 1; i <= n; ++i) cin >> a[i]; if(Sub14::valid_input()) Sub14::solve(); else if(Sub2::valid_input()) Sub2::solve(); else if(Sub3::valid_input()) Sub3::solve(); else Sub5::solve(); } int32_t main() { cin.tie(nullptr)->sync_with_stdio(0); #define task "troll" if(fopen(task".inp", "r")){ freopen(task".inp", "r", stdin); freopen(task".out", "w", stdout); } int test = 1; // cin >> test; for(int i = 1; i <= test; ++i){ // cout << "Case #" << i << ": "; solve(); } #ifdef LOCAL cerr << "\n[Time]: " << 1000.0 * clock() / CLOCKS_PER_SEC << " ms.\n"; #endif return 0; }

Compilation message (stderr)

Discharging.cpp:26:9: warning: #pragma once in main file
   26 | #pragma once
      |         ^~~~
Discharging.cpp: In function 'int32_t main()':
Discharging.cpp:222:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  222 |         freopen(task".inp", "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
Discharging.cpp:223:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  223 |         freopen(task".out", "w", stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#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...