제출 #1315969

#제출 시각아이디문제언어결과실행 시간메모리
1315969joonwu04나일강 (IOI24_nile)C++20
100 / 100
146 ms18000 KiB
#include "nile.h" #include <iostream> #include <vector> #include <array> #include <algorithm> #include <cassert> #include <climits> #include <set> #include <tuple> using namespace std; using ll = long long; bool debug = false; struct Input { vector<int>& W; vector<int>& A; vector<int>& B; vector<int>& E; }; namespace Subtask7 { ll ID_MIN = LLONG_MAX; struct Item { int W, A, B; }; class IntervalItemSet { int n = 0; vector<Item>& items; ll totalCost = 0; struct IntervalItem { int s, e; ll sumB = 0; ll evenIdxMinP = 0, oddIdxMinP = 0, passingIdxMinP = 0; ll cost = 0; int size() const { return e - s + 1; } ll renewCost() { if (size() % 2 == 0) cost = sumB; else cost = sumB + min(evenIdxMinP, passingIdxMinP); return cost; } ll getCost() const { return cost; } bool operator<(const IntervalItem& o) const { return pair{s, e} < pair{o.s, o.e}; } }; set<IntervalItem> intervalSet; set<IntervalItem>::iterator getIntervalIt(int i) { auto it = intervalSet.upper_bound(IntervalItem{i, n}); assert(it != intervalSet.begin()); --it; return it; } void insert(const IntervalItem& iit) { auto [it, inserted] = intervalSet.insert(iit); assert(inserted); totalCost += it->getCost(); } void erase(set<IntervalItem>::iterator it) { totalCost -= it->getCost(); intervalSet.erase(it); } public: IntervalItemSet() = default; explicit IntervalItemSet(vector<Item>& items_) : items(items_), totalCost(0) { n = (int)items.size(); for (int i = 0; i < n; ++i) { IntervalItem iit{i, i}; iit.sumB = items[i].B; iit.evenIdxMinP = items[i].A - items[i].B; iit.oddIdxMinP = ID_MIN; iit.passingIdxMinP = ID_MIN; iit.renewCost(); insert(iit); } } ll getTotalCost() const { return totalCost; } IntervalItem getUnionedInterval(IntervalItem aInterval, IntervalItem bInterval) { assert(aInterval.s != bInterval.s); if (aInterval.s > bInterval.s) swap(aInterval, bInterval); assert(aInterval.e + 1 == bInterval.s); IntervalItem unioned{aInterval.s, bInterval.e}; unioned.sumB = aInterval.sumB + bInterval.sumB; if (aInterval.size() % 2 == 0) { unioned.evenIdxMinP = min(aInterval.evenIdxMinP, bInterval.evenIdxMinP); unioned.oddIdxMinP = min(aInterval.oddIdxMinP, bInterval.oddIdxMinP); unioned.passingIdxMinP = min(aInterval.passingIdxMinP, bInterval.passingIdxMinP); } else { unioned.evenIdxMinP = min(aInterval.evenIdxMinP, bInterval.oddIdxMinP); unioned.oddIdxMinP = min(aInterval.oddIdxMinP, bInterval.evenIdxMinP); unioned.passingIdxMinP = min(aInterval.passingIdxMinP, bInterval.passingIdxMinP); } unioned.renewCost(); return unioned; } bool unionInterval(int a, int b) { auto aIntervalIt = getIntervalIt(a); auto bIntervalIt = getIntervalIt(b); if (aIntervalIt == bIntervalIt) { if (a > b) swap(a, b); // if (debug) assert(a + 2 == b); assert(a + 2 == b); // auto& minP = aIntervalIt->passingIdxMinP; // minP = min(minP, (ll)items[a+1].A - items[a+1].B); IntervalItem unioned = *aIntervalIt; erase(aIntervalIt); if (debug) printf("(a, b) = (%d, %d)\n", a, b); unioned.passingIdxMinP = min(unioned.passingIdxMinP, (ll)items[a+1].A - items[a+1].B); unioned.renewCost(); insert(unioned); return false; } else { IntervalItem aInterval = *aIntervalIt; IntervalItem bInterval = *bIntervalIt; erase(aIntervalIt); erase(bIntervalIt); IntervalItem unioned = getUnionedInterval(aInterval, bInterval); insert(unioned); return true; } } }; vector<Item> makeItems(vector<int>& W, vector<int>& A, vector<int>& B) { int n = (int)W.size(); vector<Item> items(n); for (int i = 0; i < n; ++i) { items[i] = Item{W[i], A[i], B[i]}; } return items; } struct Edge { int a, b; int d; }; vector<pair<int, int>> makeDIdxPairs(const vector<int>& E) { vector<pair<int, int>> DIdxPairs; DIdxPairs.reserve(E.size()); for (int i = 0; i < (int)E.size(); ++i) { DIdxPairs.emplace_back(E[i], i); } return DIdxPairs; } vector<ll> solve(vector<int>& W, vector<int>& A, vector<int>& B, vector<int>& E) { int Q = (int)E.size(); int n = (int)W.size(); // 1. sort (E, index) pairs by E vector<pair<int, int>> DIdxPairs = makeDIdxPairs(E); sort(DIdxPairs.begin(), DIdxPairs.end()); // 2. make items sorted by W vector<Item> items = makeItems(W, A, B); sort(items.begin(), items.end(), [](const Item& a, const Item& b) { return a.W < b.W; }); // 3. make edges vector<Edge> edges; for (int i = 0; i < n-1; ++i) { edges.push_back({i, i + 1, items[i+1].W - items[i].W}); } for (int i = 0; i < n-2; ++i) { edges.push_back({i, i + 2, items[i+2].W - items[i].W}); } sort(edges.begin(), edges.end(), [](const Edge& e1, const Edge& e2) { return tuple{e1.d, e1.b - e1.a} < tuple{e2.d, e2.b - e2.a}; }); vector<ll> R(Q, 0); IntervalItemSet iits(items); int i = 0, j = 0; while (i < (int)edges.size()) { Edge curEdge = edges[i]; int d = curEdge.d; while (j < Q) { auto [D, idx] = DIdxPairs[j]; if (!(D < d)) break; R[idx] = iits.getTotalCost(); ++j; } if (j >= Q) break; while (i < (int)edges.size() && edges[i].d == d) { iits.unionInterval(edges[i].a, edges[i].b); ++i; } } while (j < Q) { auto [_, idx] = DIdxPairs[j]; R[idx] = iits.getTotalCost(); ++j; } return R; } inline vector<ll> solve(const Input& in) { return solve(in.W, in.A, in.B, in.E); } } vector<ll> calculate_costs( vector<int> W, vector<int> A, vector<int> B, vector<int> E) { int Q = (int)E.size(); Input in{W, A, B, E}; return Subtask7::solve(in); }
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...