# | 제출 시각 | 아이디 | 문제 | 언어 | 결과 | 실행 시간 | 메모리 |
---|---|---|---|---|---|---|---|
973215 | wapas | Salesman (IOI09_salesman) | C++17 | 346 ms | 32940 KiB |
이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
// code by wapas
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
/*
segtree code by : https://github.com/atcoder/ac-library/blob/master/atcoder/segtree.hpp
how to use : https://github.com/atcoder/ac-library/blob/master/document_en/segtree.md
*/
#if __cplusplus < 202002L
unsigned int bit_ceil(unsigned int n) {
unsigned int x = 1;
while (x < (unsigned int)(n)) x *= 2;
return x;
}
#endif
int countr_zero(unsigned int n) {
#ifdef _MSC_VER
unsigned long index;
_BitScanForward(&index, n);
return index;
#else
return __builtin_ctz(n);
#endif
}
template <class S, auto op, auto e> struct segtree {
static_assert(is_convertible_v<decltype(op), function<S(S, S)>>,
"op must work as S(S, S)");
static_assert(is_convertible_v<decltype(e), function<S()>>,
"e must work as S()");
public:
segtree() : segtree(0) {}
explicit segtree(int n) : segtree(vector<S>(n, e())) {}
explicit segtree(const vector<S>& v) : _n(int(v.size())) {
size = (int) bit_ceil((unsigned int)(_n));
log = countr_zero((unsigned int)size);
d = vector<S>(2 * size, e());
for (int i = 0; i < _n; i++) d[size + i] = v[i];
for (int i = size - 1; i >= 1; i--) {
update(i);
}
}
void set(int p, S x) {
assert(0 <= p && p < _n);
p += size;
d[p] = x;
for (int i = 1; i <= log; i++) update(p >> i);
}
S get(int p) const {
assert(0 <= p && p < _n);
return d[p + size];
}
S prod(int l, int r) const {
assert(0 <= l && l <= r && r <= _n);
S sml = e(), smr = e();
l += size;
r += size;
while (l < r) {
if (l & 1) sml = op(sml, d[l++]);
if (r & 1) smr = op(d[--r], smr);
l >>= 1;
r >>= 1;
}
return op(sml, smr);
}
S all_prod() const { return d[1]; }
template <bool (*f)(S)> int max_right(int l) const {
return max_right(l, [](S x) { return f(x); });
}
template <class F> int max_right(int l, F f) const {
assert(0 <= l && l <= _n);
assert(f(e()));
if (l == _n) return _n;
l += size;
S sm = e();
do {
while (l % 2 == 0) l >>= 1;
if (!f(op(sm, d[l]))) {
while (l < size) {
l = (2 * l);
if (f(op(sm, d[l]))) {
sm = op(sm, d[l]);
l++;
}
}
return l - size;
}
sm = op(sm, d[l]);
l++;
} while ((l & -l) != l);
return _n;
}
template <bool (*f)(S)> int min_left(int r) const {
return min_left(r, [](S x) { return f(x); });
}
template <class F> int min_left(int r, F f) const {
assert(0 <= r && r <= _n);
assert(f(e()));
if (r == 0) return 0;
r += size;
S sm = e();
do {
r--;
while (r > 1 && (r % 2)) r >>= 1;
if (!f(op(d[r], sm))) {
while (r < size) {
r = (2 * r + 1);
if (f(op(d[r], sm))) {
sm = op(d[r], sm);
r--;
}
}
return r + 1 - size;
}
sm = op(d[r], sm);
} while ((r & -r) != r);
return 0;
}
private:
int _n, size, log;
vector<S> d;
void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};
struct market {
ll date, pos, profit;
bool operator < (const market &o) const {
if (date == o.date) return pos < o.pos;
return date < o.date;
}
};
ll op(ll a, ll b) {
return max(a, b);
}
const ll inf = -1e18;
ll e() {
return inf;
}
#define SEG_MAX 500002
void solution(int t) {
int N, U, D, S; cin >> N >> U >> D >> S;
vector<market> arr;
arr.push_back({ 0, S, 0 });
arr.push_back({ (int) 1e8, S, 0 });
arr.push_back({ (int) 1e9, S, 0 });
for (int i = 0; i < N; i++) {
ll d, p, c; cin >> d >> p >> c;
arr.push_back({ d, p, c });
}
N += 3;
ll ans = 0;
sort(arr.begin(), arr.end());
segtree<ll, op, e> stD(SEG_MAX), stU(SEG_MAX);
stD.set(S, arr[0].pos * D); stU.set(S, -arr[0].pos * U);
ll last = arr[1].date, lastIdx = 1;
for (int i = 1; i < N; i++) {
if (last == arr[i].date) continue;
int M = i - lastIdx;
vector<ll> cacheD(M, inf), cacheU(M, inf);
for (int j = 0; j < M; j++) {
int k = lastIdx + j;
ll res = inf;
res = max(res, stD.prod(0, arr[k].pos) - arr[k].pos * D);
res = max(res, stU.prod(arr[k].pos + 1, SEG_MAX) + arr[k].pos * U);
cacheD[j] = cacheU[j] = res;
}
for (int j = 0; j < M; j++) {
int k = lastIdx + j;
if (j != 0) cacheD[j] = max(cacheD[j], cacheD[j - 1] - (arr[k].pos - arr[k - 1].pos) * D);
cacheD[j] += arr[k].profit;
}
for (int j = M - 1; j >= 0; j--) {
int k = lastIdx + j;
if (j != M - 1) cacheU[j] = max(cacheU[j], cacheU[j + 1] - (arr[k + 1].pos - arr[k].pos) * U);
cacheU[j] += arr[k].profit;
}
for (int j = 0; j < M; j++) {
int k = lastIdx + j;
ll res = max(cacheD[j], cacheU[j]);
if (i == N - 1) cout << res;
stD.set(arr[k].pos, res + arr[k].pos * D);
stU.set(arr[k].pos, res - arr[k].pos * U);
}
last = arr[i].date; lastIdx = i;
}
}
int main() {
ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
// int T; cin >> T;
int T = 1;
for (int t = 0; t < T; t++) {
solution(t);
}
}
컴파일 시 표준 에러 (stderr) 메시지
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |