Submission #479412

#TimeUsernameProblemLanguageResultExecution timeMemory
479412tranxuanbachBuilding Bridges (CEOI17_building)C++17
100 / 100
116 ms13604 KiB
#include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> using namespace std; using namespace __gnu_pbds; // Optimization #pragma GCC optimize("O3,unroll-loops,no-stack-protector") #define endl '\n' // Shortcut #define int long long #define eb emplace_back #define pb push_back #define pob pop_back #define mp make_pair #define upb upper_bound #define lwb lower_bound #define fi first #define se second #define For(i, l, r) for (int i = l; i < r; i++) #define ForE(i, l, r) for (int i = l; i <= r; i++) #define Ford(i, r, l) for (int i = r; i > l; i--) #define FordE(i, r, l) for (int i = r; i >= l; i--) #define Fora(i, a) for (auto i : a) // I/O & Debug #define PrintV(a) Fora(iiii, a) cout << iiii << ' '; cout << endl; #define PrintVl(a) Fora(iiii, a) cout << iiii << endl; #define PrintA(a, l, r) for (int iiii = l; iiii <= r; iiii++) cout << a[iiii] << ' '; cout << endl; #define PrintAl(a, l, r) for (int iiii = l; iiii <= r; iiii++) cout << a[iiii] << endl; #define Ptest(x) return cout << x, 0; #define gl(s) getline(cin, s); #define setpre(x) fixed << setprecision(x) /* #define debug(args...){ string _sDEB = #args; replace(_sDEB.begin(), _sDEB.end(), ',', ' '); stringstream _ssDEB(_sDEB); istream_iterator<string> _itDEB(_ssDEB); DEB(_itDEB, args); } void DEB(istream_iterator<string> it) {} template<typename T, typename... Args> void DEB(istream_iterator<string> it, T a, Args... args){ cout << *it << " = " << a << endl; DEB(++it, args...); } */ // Functions //#define isvowel(a) (a == 'a' || a == 'e' || a == 'i' || a == 'o' || a == 'u') #define bend(a) a.begin(), a.end() #define rbend(a) a.rbegin(), a.rend() #define mset(a) memset(a, 0, sizeof(a)) #define mset1(a) memset(a, 1, sizeof(a)) #define msetn1(a) memset(a, -1, sizeof(a)) #define msetinf(a) memset(a, 0x3f, sizeof(a)) #define gcd __gcd #define __builtin_popcount __builtin_popcountll //mt19937 rando(chrono::steady_clock::now().time_since_epoch().count()); //int randt(int l, int r){ return (rando() % (r - l + 1) + l); } // Data Structure #define pque priority_queue #define mts multiset #define y0 _y0_ #define y1 _y1_ #define div divi typedef long long ll; typedef long double ld; typedef vector <int> vi; typedef vector <ll> vll; typedef vector <ld> vld; typedef vector <string> vs; typedef pair <int, int> pii; typedef pair <ll, ll> pll; typedef vector <vi > vvi; typedef vector <vll > vvll; typedef vector <pii > vpii; typedef vector <pll > vpll; const int N = 1e5 + 5; int mod = 1e9 + 7, mod1 = 998244353, mod2 = 1e9 + 9, inf = 1e9 + 7; ll infll = 1e18 + 7; /* * Dynamic version of data structure * to be used in dynamic programming optimisation * called "Convex Hull trick" * 'Dynamic' means that there is no restriction on adding lines order */ class ConvexHullDynamic { typedef long long coef_t; typedef long long coord_t; typedef long long val_t; /* * Line 'y=a*x+b' represented by 2 coefficients 'a' and 'b' * and 'xLeft' which is intersection with previous line in hull(first line has -INF) */ private: struct Line { coef_t a, b; ld xLeft; enum Type {line, maxQuery, minQuery} type; coord_t val; explicit Line(coef_t aa=0, coef_t bb=0) : a(aa), b(bb), xLeft(-infll), type(Type::line), val(0) {} val_t valueAt(coord_t x) const { return a*x+b; } friend bool areParallel(const Line& l1, const Line& l2) { return l1.a==l2.a; } friend ld intersectX(const Line& l1, const Line& l2) { return areParallel(l1,l2)?infll:1.0*(l2.b-l1.b)/(l1.a-l2.a); } bool operator<(const Line& l2) const { if (l2.type == line) return this->a < l2.a; if (l2.type == maxQuery) return this->xLeft < l2.val; if (l2.type == minQuery) return this->xLeft > l2.val; } }; private: bool isMax; //whether or not saved envelope is top(search of max value) std::set<Line> hull; //envelope itself private: /* * INFO: Check position in hull by iterator * COMPLEXITY: O(1) */ bool hasPrev(std::set<Line>::iterator it) { return it!=hull.begin(); } bool hasNext(std::set<Line>::iterator it) { return it!=hull.end() && std::next(it)!=hull.end(); } /* * INFO: Check whether line l2 is irrelevant * NOTE: Following positioning in hull must be true * l1 is next left to l2 * l2 is right between l1 and l3 * l3 is next right to l2 * COMPLEXITY: O(1) */ bool irrelevant(const Line& l1, const Line& l2, const Line& l3) { return intersectX(l1,l3) <= intersectX(l1,l2); } bool irrelevant(std::set<Line>::iterator it) { return hasPrev(it) && hasNext(it) && ( isMax && irrelevant(*std::prev(it), *it, *std::next(it)) || !isMax && irrelevant(*std::next(it), *it, *std::prev(it)) ); } /* * INFO: Updates 'xValue' of line pointed by iterator 'it' * COMPLEXITY: O(1) */ std::set<Line>::iterator updateLeftBorder(std::set<Line>::iterator it) { if (isMax && !hasPrev(it) || !isMax && !hasNext(it)) return it; double val = intersectX(*it, isMax?*std::prev(it):*std::next(it)); Line buf(*it); it = hull.erase(it); buf.xLeft = val; it = hull.insert(it, buf); return it; } public: explicit ConvexHullDynamic(bool isMax): isMax(isMax) {} /* * INFO: Adding line to the envelope * Line is of type 'y=a*x+b' represented by 2 coefficients 'a' and 'b' * COMPLEXITY: Adding N lines(N calls of function) takes O(N*log N) time */ void addLine(coef_t a, coef_t b) { //find the place where line will be inserted in set Line l3 = Line(a, b); auto it = hull.lower_bound(l3); //if parallel line is already in set, one of them becomes irrelevant if (it!=hull.end() && areParallel(*it, l3)) { if (isMax && it->b < b || !isMax && it->b > b) it = hull.erase(it); else return; } //try to insert it = hull.insert(it, l3); if (irrelevant(it)) { hull.erase(it); return; } //remove lines which became irrelevant after inserting line while (hasPrev(it) && irrelevant(std::prev(it))) hull.erase(std::prev(it)); while (hasNext(it) && irrelevant(std::next(it))) hull.erase(std::next(it)); //refresh 'xLine' it = updateLeftBorder(it); if (hasPrev(it)) updateLeftBorder(std::prev(it)); if (hasNext(it)) updateLeftBorder(std::next(it)); } /* * INFO: Query, which returns max/min(depends on hull type - see more info above) value in point with abscissa 'x' * COMPLEXITY: O(log N), N-amount of lines in hull */ val_t getBest(coord_t x) const { Line q; q.val = x; q.type = isMax ? Line::Type::maxQuery : Line::Type::minQuery; auto bestLine = hull.lower_bound(q); if (isMax) --bestLine; return bestLine->valueAt(x); } } dch(0); int n; int h[N], w[N], b[N], dp[N]; signed main(){ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n; ForE(i, 1, n){ cin >> h[i]; } ForE(i, 1, n){ cin >> w[i]; b[i] = b[i - 1] + w[i]; } dp[1] = 0; dch.addLine(-2 * h[1], dp[1] - b[1] + h[1] * h[1]); // cout << dch.getBest(h[1]) << ' '; ForE(i, 2, n){ dp[i] = b[i - 1] + h[i] * h[i] + dch.getBest(h[i]); // cout << dch.getBest(h[i]) << ' '; dch.addLine(-2 * h[i], dp[i] - b[i] + h[i] * h[i]); } // cout << endl; // PrintA(dp, 1, n); cout << dp[n]; } /* ==================================+ INPUT: | ------------------------------ | ------------------------------ | ==================================+ OUTPUT: | ------------------------------ | ------------------------------ | ==================================+ */

Compilation message (stderr)

building.cpp: In member function 'bool ConvexHullDynamic::irrelevant(std::set<ConvexHullDynamic::Line>::iterator)':
building.cpp:150:30: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
  150 |                && (    isMax && irrelevant(*std::prev(it), *it, *std::next(it))
      |                        ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
building.cpp: In member function 'std::set<ConvexHullDynamic::Line>::iterator ConvexHullDynamic::updateLeftBorder(std::set<ConvexHullDynamic::Line>::iterator)':
building.cpp:160:19: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
  160 |         if (isMax && !hasPrev(it) || !isMax && !hasNext(it))
      |             ~~~~~~^~~~~~~~~~~~~~~
building.cpp: In member function 'void ConvexHullDynamic::addLine(ConvexHullDynamic::coef_t, ConvexHullDynamic::coef_t)':
building.cpp:188:23: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
  188 |             if (isMax && it->b < b || !isMax && it->b > b)
      |                 ~~~~~~^~~~~~~~~~~~
building.cpp: In member function 'bool ConvexHullDynamic::Line::operator<(const ConvexHullDynamic::Line&) const':
building.cpp:123:9: warning: control reaches end of non-void function [-Wreturn-type]
  123 |         }
      |         ^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...