Submission #921865

#TimeUsernameProblemLanguageResultExecution timeMemory
921865josanneo22Salesman (IOI09_salesman)C++17
62 / 100
821 ms57436 KiB
#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;
	}
	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], actual_pos[0] * U);
	back.update(1, 1, M, pos[0], -actual_pos[0] * D);
	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]] * U;
		val_back = val_back + actual_pos[ord[i]] * D;
		dp[i] = max(val_front, val_back) + profit[ord[i]];
		front.update(1, 1, M, pos[ord[i]], dp[i] + actual_pos[ord[i]] * U);
		back.update(1, 1, M, pos[ord[i]], dp[i] - actual_pos[ord[i]] * D);
	}
	cout << max(0LL, dp[N + 1]) << '\n';
}

Compilation message (stderr)

salesman.cpp:1: warning: ignoring '#pragma warning ' [-Wunknown-pragmas]
    1 | #pragma warning(suppress : 4996)
      |
#Verdict Execution timeMemoryGrader output
Fetching results...