(UPD: 2024-12-04 14:48 UTC) Judge is not working due to Cloudflare incident. (URL) We can do nothing about it, sorry. After the incident is resolved, we will grade all submissions.

Submission #413979

#TimeUsernameProblemLanguageResultExecution timeMemory
413979usachevd0Meetings (IOI18_meetings)C++14
100 / 100
3483 ms361888 KiB
#include <bits/stdc++.h> #ifndef LOCAL #include "meetings.h" #endif using namespace std; #define fi first #define se second #define mp make_pair #define pb push_back #define all(a) (a).begin(), (a).end() #define Time (clock() * 1.0 / CLOCKS_PER_SEC) using ll = long long; using ull = unsigned long long; using pii = pair<int, int>; using pil = pair<int, ll>; using pli = pair<ll, int>; using pll = pair<ll, ll>; using ld = long double; template<typename T1, typename T2> bool chkmin(T1& x, T2 y) { return y < x ? (x = y, true) : false; } template<typename T1, typename T2> bool chkmax(T1& x, T2 y) { return y > x ? (x = y, true) : false; } void debug_out() { cerr << endl; } template<typename T1, typename... T2> void debug_out(T1 A, T2... B) { cerr << ' ' << A; debug_out(B...); } template<typename T> void mdebug_out(T* a, int n) { for (int i = 0; i < n; ++i) cerr << a[i] << ' '; cerr << endl; } #ifdef LOCAL #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__) #define mdebug(a, n) cerr << #a << ": ", mdebug_out(a, n) #else #define debug(...) 1337 #define mdebug(a, n) 1337 #endif template<typename T> ostream& operator << (ostream& stream, const vector<T>& v) { for (auto& x : v) stream << x << ' '; return stream; } template<typename T1, typename T2> ostream& operator << (ostream& stream, const pair<T1, T2>& p) { return stream << p.first << ' ' << p.second; } template<typename T> ostream& operator << (ostream& stream, const deque<T>& v) { for (auto& x : v) stream << x << ' '; return stream; } #ifdef LOCAL mt19937 rng(1337); #else mt19937 rng(2122); #endif const int INF32 = 1e9; const ll INF64 = 1e18; const int maxN = 750005; int n, Q; int a[maxN]; int randY[maxN], irandY[maxN]; vector<int> que[maxN]; namespace sgt { const int logN = 20; const int N = 1 << logN; pii t[2 * N]; void build() { for (int i = 0; i < n; ++i) t[i + N] = mp(a[i], randY[i]); for (int i = N - 1; i >= 1; --i) { t[i] = max(t[i << 1], t[i << 1 | 1]); } } int argmax(int l, int r) { pii ans = {-INF32, -INF32}; for (l += N, r += N; l <= r; l >>= 1, r >>= 1) { if (l & 1) chkmax(ans, t[l++]); if (~r & 1) chkmax(ans, t[r--]); } return irandY[ans.se]; } } struct line { int k; ll b; line() {} line(ll _k, ll _b): k(_k), b(_b) {} ll f(ll x) { return k * x + b; } }; ostream& operator << (ostream& stream, const line& l) { return stream << l.k << "i + " << l.b; } double intersect(const line& lhs, const line& rhs) { return (rhs.b - lhs.b) / (double)(lhs.k - rhs.k); } namespace treap { struct Node { int y, sz; Node *l, *r; line e; int L; Node(line _e, int _L) { y = rng(); sz = 1; l = r = 0; e = _e; L = _L; } }; int sz(Node* t) { return t ? t->sz : 0; } void upd(Node* t) { if (t) { t->sz = sz(t->l) + 1 + sz(t->r); } } Node* merge(Node* a, Node* b) { if (!a) return b; if (!b) return a; if (a->y > b->y) { a->r = merge(a->r, b); upd(a); return a; } else { b->l = merge(a, b->l); upd(b); return b; } } void clear(Node *t) { if (!t) return; clear(t->l); clear(t->r); // delete t; } pair<line, int> getLeft(Node *t) { assert(t); while (t->l) t = t->l; return {t->e, t->L}; } void removeLeft(Node*& t) { if (!t) return; if (t->l) { removeLeft(t->l); upd(t); } else { auto tt = merge(t->l, t->r); // delete t; t = tt; } } void addToAll(Node* t, ll delta) { if (!t) return; addToAll(t->l, delta); t->e.b += delta; addToAll(t->r, delta); } ll f(Node *t, int i) { ll ans = 0; while (t) { if (t->L <= i) { ans = t->e.f(i); t = t->r; } else { t = t->l; } } return ans; } } struct DS { ll delta; treap::Node* T; int R; DS() { delta = 0; T = 0; } DS(ll x, int l) { delta = 0; T = new treap::Node({0, x}, l); } void clear() { delta = 0; treap::clear(T); T = 0; } int size() { return treap::sz(T); } void pushBack(line e, int l) { e.b -= delta; T = treap::merge(T, new treap::Node(e, l)); } void pushFront(line e, int l) { e.b -= delta; T = treap::merge(new treap::Node(e, l), T); } void pushBack(int i, ll x) { x -= delta; T = treap::merge(T, new treap::Node({0, x}, i)); } void pushFront(int i, ll x) { x -= delta; T = treap::merge(new treap::Node({0, x}, i), T); } void add(ll d) { delta += d; } void relaxPrefix(line e) { /*if (val.empty()) return; e.b -= delta; if (val[0].f(L[0]) <= e.f(L[0])) return; int l = L[0]; while (!val.empty() && val[0].f(L[0]) > e.f(L[0])) { int r = (val.size() > 1 ? L[1] - 1 : R); if (val[0].f(r) >= e.f(r)) { val.pop_front(); L.pop_front(); } else { L[0] = ceil(intersect(e, val[0])); break; } } val.push_front(e); L.push_front(l);*/ if (!T) return; e.b -= delta; line e1; int L1; tie(e1, L1) = treap::getLeft(T); int l = L1; if (e1.f(L1) <= e.f(L1)) return; while (T && e1.f(L1) > e.f(L1)) { treap::removeLeft(T); int r = T ? treap::getLeft(T).se - 1 : R; if (e1.f(r) >= e.f(r)) { if (!T) break; tie(e1, L1) = treap::getLeft(T); } else { T = treap::merge(new treap::Node(e1, ceil(intersect(e, e1))), T); break; } } T = treap::merge(new treap::Node(e, l), T); } ll f(int i) { // int t = upper_bound(all(L), i) - L.begin() - 1; // if (t < 0) return 0; // return val[t].f(i) + delta; if (!T || treap::getLeft(T).se > i) return 0; return treap::f(T, i) + delta; } };// PP[maxN]; vector<ll> minimum_costs(vector<int> _a, vector<int> ql, vector<int> qr) { n = _a.size(), Q = ql.size(); for (int i = 0; i < n; ++i) a[i] = _a[i]; iota(randY, randY + n, 0); shuffle(randY, randY + n, rng); for (int i = 0; i < n; ++i) irandY[randY[i]] = i; vector<ll> ans(Q, INF64); for (int rot = 0; rot < 2; ++rot) { for (int i = 0; i < n; ++i) { que[i].clear(); // PP[i].clear(); } sgt::build(); for (int i = 0; i < Q; ++i) { int j = sgt::argmax(ql[i], qr[i]); que[j].push_back(i); } function<DS(int, int)> solve = [&](int L, int R) { if (L > R) return DS(); int I = sgt::argmax(L, R); ll M = a[I]; // debug(L, I, R); // auto& P = PP[I]; // int IL = solve(L, I - 1); // auto& PL = PP[IL]; // int IR = solve(I + 1, R); // auto& PR = PP[IR]; DS P; P.R = R; DS PL = solve(L, I - 1); DS PR = solve(I + 1, R); for (int q : que[I]) { int l = ql[q], r = qr[q]; chkmin(ans[q], PR.f(r) + M * (I - l + 1)); } PR.add(M * (I - L + 1)); PR.relaxPrefix({M, PL.f(I - 1) - M * (I - 1)}); if (PR.size() <= PL.size()) { swap(P, PL); P.R = R; P.pushBack(I, P.f(I - 1) + M); // for (int i = 0; i < PR.size(); ++i) { // line e = PR.val[i]; // e.b += PR.delta; // int l = PR.L[i]; // P.pushBack(e, l); // } // for (int i = I + 1, t = 0; i <= R; ++i) { // while (t + 1 < PR.size() && PR.L[t + 1] <= i) // ++t; // P.pushBack(i, PR.val[t].f(i) + PR.delta); // } treap::addToAll(PR.T, + PR.delta - P.delta); P.T = treap::merge(P.T, PR.T); PR.clear(); } else { swap(P, PR); P.R = R; P.pushFront(I, PL.f(I - 1) + M); // for (int i = (int)PL.size() - 1; i >= 0; --i) { // line e = PL.val[i]; // e.b += PL.delta; // int l = PL.L[i]; // P.pushFront(e, l); // } // for (int i = I - 1, t = PL.size() - 1; i >= L; --i) { // while (PL.L[t] > i) // --t; // P.pushFront(i, PL.val[t].f(i) + PL.delta); // } treap::addToAll(PL.T, + PL.delta - P.delta); P.T = treap::merge(PL.T, P.T); PL.clear(); } // debug(L, I, R); // for (int i = L; i <= R; ++i) // cerr << P.f(i) << ' '; // cerr << endl; return P; // return I; }; auto P = solve(0, n - 1); P.clear(); reverse(a, a + n); reverse(randY, randY + n); for (int i = 0; i < n; ++i) irandY[randY[i]] = i; for (int i = 0; i < Q; ++i) { ql[i] = n - ql[i] - 1; qr[i] = n - qr[i] - 1; swap(ql[i], qr[i]); } } return ans; } #ifdef LOCAL int read_int() { int x; if (scanf("%d", &x) != 1) { fprintf(stderr, "Error while reading input\n"); exit(1); } return x; } int32_t main() { #ifdef LOCAL freopen("in", "r", stdin); #endif ios::sync_with_stdio(0); cin.tie(0); int N = read_int(); int Q = read_int(); std::vector<int> H(N); for (int i = 0; i < N; ++i) { H[i] = read_int(); } std::vector<int> L(Q), R(Q); for (int j = 0; j < Q; ++j) { L[j] = read_int(); R[j] = read_int(); } std::vector<long long> C = minimum_costs(H, L, R); for (size_t j = 0; j < C.size(); ++j) { printf("%lld\n", C[j]); } return 0; return 0; } #endif
#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...