제출 #529429

#제출 시각아이디문제언어결과실행 시간메모리
529429GraphterAliens (IOI16_aliens)C++17
100 / 100
1847 ms5748 KiB
#include <bits/stdc++.h> #define debug(x) cout << #x << " = " << x << endl #define REP(i, n) for (Long i = 0; i < (Long)n; i++) using namespace std; typedef long long Long; //https://contest.yandex.com/ioi/contest/2830/problems/F/ const Long INF = 1e18; struct Line { mutable Long m, b; //mx + b, intersect with next line at r (rounded down) Line() {} Line(Long m, Long b): m(m), b(b){} Long getVal(Long x) {return m * x + b;} }; struct CHT{ deque<Line> envelope; Long div(Long a, Long b) { //floored division //CAREFUL ! this won't produced the right convex envelope //but the maxY function will still work for integers //if you need the correct convex envelope, use double division //or multiplication in "bad" function assert(b != 0); return a / b - ((a ^ b) < 0 && a % b); } Long intersect(Line l1, Line l2) { return div(l1.b - l2.b, l2.m - l1.m); } bool bad(Line l1, Line l2, Line l3) { //tells if l2 is bad an can be eliminated by l3 return intersect(l2 , l3) <= intersect(l1, l2); } void addLine(Line l3) { l3.m *= -1; l3.b *= -1; if (envelope.empty()) { envelope.push_back(l3); return; } if (l3.m == envelope.back().m) { if (l3.b > envelope.back().b) envelope.pop_back(); else return; } if (envelope.size() <= 1) { envelope.push_back(l3); return; } Long sz = envelope.size(); Line l1 = envelope[sz - 2]; Line l2 = envelope[sz - 1]; while (bad(l1, l2, l3)) { envelope.pop_back(); if (envelope.size() == 1) break; sz = envelope.size(); l1 = envelope[sz - 2]; l2 = envelope[sz - 1]; } envelope.push_back(l3); } Long minY(Long x) { //O(log n) assert(!envelope.empty()); while (envelope.size() >= 2 && envelope[0].getVal(x) < envelope[1].getVal(x)) { envelope.pop_front(); } return -envelope[0].getVal(x); } }; struct Range { int l, r; Range(int l, int r): l(l), r(r){} bool operator <(const Range &other) { return r < other.r; } bool contains(Range &other) { return l <= other.l && other.r <= r; } }; void removeContained(vector<Range> &v) { int n = v.size(); vector<Range> ans = {v.back()}; for (int i = n - 2; i >= 0; i--) { if (ans.back().contains(v[i])) continue; ans.push_back(v[i]); } reverse(ans.begin(), ans.end()); v = ans; } Long square(Long x) { return x * x; } vector<int> L, R; Long cost(int l, int r) { Long ans = square(R[r] - L[l]); if (l > 0) ans -= square(max(0, R[l - 1] - L[l])); return ans; } struct OptRange { int l, r, opt; OptRange(int l, int r, int opt): l(l), r(r), opt(opt){} }; Long getBest(Long lambda, int k) { int n = L.size(); vector<Long> dp(n); dp[0] = cost(0, 0) - lambda; deque<OptRange> ranges = {OptRange(1, n - 1, -1)}; auto getOptimum = [&](int i, int opt) { if (opt == -1) return cost(0, i) - lambda; assert(opt + 1 <= i); return dp[opt] + cost(opt + 1, i) - lambda; }; for (int i = 0; i + 1 < n; i++) { assert(ranges.front().l == i + 1); auto improve = [&](int pos, int opt) { return getOptimum(pos, i) < getOptimum(pos, opt); }; while (!ranges.empty() && improve(ranges.back().l, ranges.back().opt)) { ranges.pop_back(); } if (ranges.empty()) ranges.push_back(OptRange(i + 1, n - 1, i)); else { int low = ranges.back().l; int high = ranges.back().r; int opt = ranges.back().opt; if (!improve(high, opt)) low = high++; // F F F ... T T T while (high - low > 1) { int mid = (low + high) / 2; if (improve(mid, opt)) high = mid; else low = mid; } ranges.back().r = low; if (high < n) ranges.push_back(OptRange(high, n - 1, i)); } dp[i + 1] = getOptimum(i + 1, ranges.front().opt); ranges.front().l++; if (ranges.front().l > ranges.front().r) ranges.pop_front(); } return dp[n - 1] + lambda * k; } const Long INF2 = 1e13; Long minCost(int k) { //O(log n) Long low = -INF2; Long high = INF2; while (high - low > 2) { Long m1 = low + (high - low) / 3; Long m2 = high - (high - low) / 3; if (getBest(m1, k) < getBest(m2, k)) low = m1; else high = m2; } Long maxi = getBest(low, k); for (Long i = low + 1; i <= high; i++) { maxi = max(maxi, getBest(i, k)); } return maxi; } Long take_photos(int n, int m, int K, vector<int> x, vector<int> y) { vector<Range> v; REP(i, n) { int l = min(x[i], y[i]); int r = max(x[i], y[i]); v.push_back({l, r}); } sort(v.begin(), v.end()); removeContained(v); n = v.size(); L = R = vector<int>(n); REP(i, n) { v[i].r++; L[i] = v[i].l; R[i] = v[i].r; } K = min(K, n); return minCost(K); } /* 5 8 5 1 5 3 4 2 6 1 4 3 5 ans = 34 7 30 5 1 5 3 4 2 6 1 4 3 5 9 15 14 22 ans = 160 */ /*int main() { ios_base::sync_with_stdio(false); cin.tie(0); int n, m, k; cin >> n >> m >> k; vector<int> x(n); vector<int> y(n); REP(i, n) { cin >> x[i] >> y[i]; } cout << take_photos(n, m, k, x, y) << "\n"; 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...