# | Time | Username | Problem | Language | Result | Execution time | Memory |
---|---|---|---|---|---|---|---|
921863 | josanneo22 | Salesman (IOI09_salesman) | C++17 | 779 ms | 57540 KiB |
This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#pragma warning(suppress : 4996)
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
#define L(i,j,k) for(int i=(j);i<=(k);++i)
#define R(i,j,k) for(int i=(j);i>=(k);--i)
#define all(x) x.begin(),x.end()
#define me(x,a) memset(x,a,sizeof(x))
struct segtree {
struct node {
i64 mx;
friend node operator + (const node& A, const node& B) {
return { max(A.mx, B.mx) };
}
};
vector<node> tr;
segtree(int n){ tr.resize(n << 2);}
void build(int p, int l, int r) {
if (l == r) {
tr[p].mx = -1E18;
return;
}
int mid = (l + r) >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
tr[p] = tr[p << 1] + tr[p << 1 | 1];
}
void update(int p, int l, int r, int x, i64 v) {
if (l == x && l == r) {
tr[p].mx = max(tr[p].mx, v);
return;
}
int mid = (l + r) >> 1;
if (x <= mid) update(p << 1, l, mid, x, v);
if (x >= mid + 1) update(p << 1 | 1, mid + 1, r, x, v);
tr[p] = tr[p << 1] + tr[p << 1 | 1];
}
node query(int p, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr) return tr[p];
if (l > qr || r < ql) return { (i64) - 1E18};
int mid = (l + r) >> 1;
if (ql <= mid && qr >= mid + 1) return query(p << 1, l, mid, ql, qr) + query(p << 1 | 1, mid + 1, r, ql, qr);
if (ql <= mid) return query(p << 1, l, mid, ql, qr);
if (qr >= mid + 1) return query(p << 1 | 1, mid + 1, r, ql, qr);
return { (i64)-1E18 };
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
int N; i64 U, D, S; cin >> N >> U >> D >> S;
//dp[i] = max profit after considering all events until i
//dp[i] = dp[j] + (pos[i] - pos[j]) * U if pos[i] <= pos[j]
//dp[i] = dp[j] + (pos[j] - pos[i]) * D if pos[i] > pos[j]
/*
if (pos[ord[i]] <= pos[ord[j]])
dp[i] = max(dp[i], dp[j] + profit[ord[i]] - (pos[ord[j]] - pos[ord[i]]) * D);
dp[i] = (max(dp[j] - pos[ord[j]] * D)) + (profit[ord[i]] + pos[ord[i]] * D);
for each j that has pos[ord[j]] > pos[ord[i]]
if we are using a segtree, we are querying on [o(pos[ord[i]), +inf)
o(x) is the relative position
then we try to set o(pos[ord[i]]) to be dp[i] (set max)
*/
vector<i64> dp(N + 2, -1E18);
vector<i64> date(N + 2), pos(N + 2), profit(N + 2);
L(i, 1, N) cin >> date[i] >> pos[i] >> profit[i];
pos[0] = S; date[0] = -1E18; pos[N + 1] = S; date[N + 1] = 1E18;
vector<int> ord(N + 2); iota(all(ord), 0);
sort(ord.begin(), ord.end(), [&](int i, int j) { return date[i] < date[j]; });
vector<i64> relative_pos, actual_pos(N + 2);
L(i, 0, N + 1) relative_pos.push_back(pos[i]);
sort(all(relative_pos));
relative_pos.resize(unique(all(relative_pos)) - relative_pos.begin());
int M = relative_pos.size();
L(i, 0, N + 1) {
actual_pos[i] = pos[i];
pos[i] = lower_bound(all(relative_pos), pos[i]) - relative_pos.begin() + 1;
}
dp[0] = 0;
segtree front(M), back(M);
front.build(1, 1, M); back.build(1, 1, M);
front.update(1, 1, M, pos[0], actual_pos[0] * D);
back.update(1, 1, M, pos[0], -actual_pos[0] * U);
L(i, 1, N + 1) {
i64 val_front = front.query(1, 1, M, 1, pos[ord[i]]).mx;
i64 val_back = back.query(1, 1, M, pos[ord[i]], M).mx;
val_front = val_front - actual_pos[ord[i]] * D;
val_back = val_back + actual_pos[ord[i]] * U;
dp[i] = max(val_front, val_back) + profit[ord[i]];
front.update(1, 1, M, pos[ord[i]], dp[i] + actual_pos[ord[i]] * D);
back.update(1, 1, M, pos[ord[i]], dp[i] - actual_pos[ord[i]] * U);
}
cout << dp[N + 1] << '\n';
}
Compilation message (stderr)
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |