# | 제출 시각 | 아이디 | 문제 | 언어 | 결과 | 실행 시간 | 메모리 |
---|---|---|---|---|---|---|---|
921899 | josanneo22 | Salesman (IOI09_salesman) | C++17 | 879 ms | 65536 KiB |
이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#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 == 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) {
if (date[i] != date[j]) return date[i] < date[j];
return pos[i] < pos[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;
}
auto dp1 = dp, dp2 = dp;
dp[0] = 0;
segtree front(M + 50), back(M + 50);
front.build(1, 1, M); back.build(1, 1, M);
front.update(1, 1, M, pos[0], S * U);
back.update(1, 1, M, pos[0], -S * D);
for(int i = 1; i <= N + 1;) {
int pt = i; while (pt + 1 <= N && date[ord[pt + 1]] == date[ord[i]]) pt++;
for (int k = i; k <= pt; k++) {
i64 val_front = front.query(1, 1, M, 1, pos[ord[k]]).mx;
i64 val_back = back.query(1, 1, M, pos[ord[k]], M).mx;
val_front = val_front - actual_pos[ord[k]] * U;
val_back = val_back + actual_pos[ord[k]] * D;
dp1[k] = dp2[k] = dp[k] = max(val_front, val_back) + profit[ord[k]];
}
for(int k = pt - 1; k >= i; k--)
dp1[k] = max(dp1[k], dp1[k + 1] + profit[ord[k]] - D * (actual_pos[ord[k + 1]] - actual_pos[ord[k]]));
for(int k = i + 1; k <= pt; k++)
dp2[k] = max(dp2[k], dp2[k - 1] + profit[ord[k]] - U * (actual_pos[ord[k]] - actual_pos[ord[k - 1]]));
L(k, i, pt) dp[k] = max(dp1[k], dp2[k]);
L(k, i, pt){
front.update(1, 1, M, pos[ord[k]], dp[k] + actual_pos[ord[k]] * U);
back.update(1, 1, M, pos[ord[k]], dp[k] - actual_pos[ord[k]] * D);
}
i = pt + 1;
}
cout << max(dp1[N + 1], dp2[N + 1]) << '\n';
}
컴파일 시 표준 에러 (stderr) 메시지
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |