Submission #928567

#TimeUsernameProblemLanguageResultExecution timeMemory
928567boris_mihovSalesman (IOI09_salesman)C++17
100 / 100
440 ms43712 KiB
#include <algorithm> #include <iostream> #include <numeric> #include <cassert> #include <vector> #include <queue> #include <set> typedef long long llong; const int MAXN = 500000 + 10; const llong INF = 1e18; int n; llong d, u; struct Event { int pos; int time; llong cost; friend bool operator < (const Event &a, const Event &b) { return a.time < b.time || (a.time == b.time && a.pos < b.pos); } }; struct SegmentTree { llong tree[4*MAXN]; void build(int l, int r, int node) { if (l == r) { tree[node] = -INF; return; } int mid = (l + r) / 2; build(l, mid, 2*node); build(mid + 1, r, 2*node + 1); tree[node] = std::max(tree[2*node], tree[2*node + 1]); } void update(int l, int r, int node, int queryPos, llong queryVal) { if (l == r) { tree[node] = std::max(tree[node], queryVal); return; } int mid = (l + r) / 2; if (queryPos <= mid) update(l, mid, 2*node, queryPos, queryVal); else update(mid + 1, r, 2*node + 1, queryPos, queryVal); tree[node] = std::max(tree[2*node], tree[2*node + 1]); } llong query(int l, int r, int node, int queryL, int queryR) { if (queryL <= l && r <= queryR) { return tree[node]; } llong res = -INF; int mid = (l + r) / 2; if (queryL <= mid) res = query(l, mid, 2*node, queryL, queryR); if (mid + 1 <= queryR) res = std::max(res, query(mid + 1, r, 2*node + 1, queryL, queryR)); return res; } void build() { build(1, MAXN - 1, 1); } void update(int pos, int val) { update(1, MAXN - 1, 1, pos, val); } llong query(int l, int r) { return query(1, MAXN - 1, 1, l, r); } }; SegmentTree treeU; SegmentTree treeD; Event event[MAXN]; llong dp[MAXN]; llong dp1[MAXN]; llong dp2[MAXN]; void solve() { treeU.build(); treeD.build(); std::sort(event + 1, event + 1 + n); int last = 1; std::vector <std::pair <int,int>> ranges; ranges.push_back({0, 0}); for (int i = 2 ; i <= n ; ++i) { if (event[i].time != event[i - 1].time) { ranges.push_back({last, i - 1}); last = i; } } ranges.push_back({last, n}); std::reverse(ranges.begin(), ranges.end()); for (const auto &[l, r] : ranges) { for (int i = r ; i >= l ; --i) { if (event[i].pos <= event[0].pos) dp[i] = -(event[0].pos - event[i].pos) * d; else dp[i] = -(event[i].pos - event[0].pos) * u; dp[i] = std::max(dp[i], treeU.query(1, event[i].pos) - event[i].pos * u); dp[i] = std::max(dp[i], treeD.query(event[i].pos, MAXN - 1) + event[i].pos * d); } llong maxToNow = -INF; llong sum = 0; for (int i = l ; i <= r ; ++i) { dp1[i] = std::max(dp[i], maxToNow - event[i].pos * u + sum); maxToNow = std::max(maxToNow, dp1[i] + event[i].pos * u - sum); sum += event[i].cost; } maxToNow = -INF; sum = 0; for (int i = r ; i >= l ; --i) { dp2[i] = std::max(dp[i], maxToNow + event[i].pos * d + sum); maxToNow = std::max(maxToNow, dp2[i] - event[i].pos * d - sum); sum += event[i].cost; } for (int i = l ; i <= r ; ++i) { dp[i] = std::max(dp1[i], dp[i]); dp[i] = std::max(dp2[i], dp[i]); treeU.update(event[i].pos, dp[i] + event[i].cost + event[i].pos * u); treeD.update(event[i].pos, dp[i] + event[i].cost - event[i].pos * d); } } std::cout << dp[0] << '\n'; } void input() { std::cin >> n >> u >> d >> event[0].pos; for (int i = 1 ; i <= n ; ++i) { std::cin >> event[i].time >> event[i].pos >> event[i].cost; } } void fastIOI() { std::ios_base :: sync_with_stdio(0); std::cout.tie(nullptr); std::cin.tie(nullptr); } int main() { fastIOI(); input(); solve(); return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...