Advertisement
erek1e

IOI '09 P8 - Salesman

Jun 26th, 2023
608
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.52 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4.  
  5. using namespace std;
  6.  
  7. const int MAX_T = 5e5, MAX_L = 5e5 + 1;
  8. const int INF = 2e9 + 1e8;
  9.  
  10. // Fenwick Tree (for prefix max)
  11. void update(vector<int> &fenwick, int index, int value) {
  12.     while (index < (int)fenwick.size()) {
  13.         fenwick[index] = max(fenwick[index], value);
  14.         index += index & -index;
  15.     }
  16. }
  17. int getMax(const vector<int> &fenwick, int index) {
  18.     int mx = -INF;
  19.     while (index) {
  20.         mx = max(mx, fenwick[index]);
  21.         index -= index & -index;
  22.     }
  23.     return mx;
  24. }
  25. // Reverse Fenwick Tree (for suffix max)
  26. void updateR(vector<int> &fenwick, int index, int value) {
  27.     update(fenwick, (int)fenwick.size()-index, value);
  28. }
  29. int getMaxR(const vector<int> &fenwick, int index) {
  30.     return getMax(fenwick, (int)fenwick.size()-index);
  31. }
  32.  
  33. vector<pair<int, int>> fairsOnDay[1+MAX_T+1];
  34.  
  35. int main() {
  36.     ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  37.     int n, U, D, S; cin >> n >> U >> D >> S;
  38.     // since you start and end at one place, only U+D matters
  39.     D += U, U = 0;
  40.     D = -D; // profit of D, D is negative
  41.  
  42.     for (int i = 0; i < n; ++i) {
  43.         int t, l, m; cin >> t >> l >> m;
  44.         fairsOnDay[t].emplace_back(l, m);
  45.     }
  46.     fairsOnDay[MAX_T+1].emplace_back(S, 0);
  47.  
  48.     // Define p[k] as the maximum profit after visiting a fair at location k up to time t
  49.     vector<int> maxP(1+MAX_L, -INF), maxDif(1+MAX_L, -INF); // two fenwick trees, one for max p[k] on suffix, one for max p[k] - D*k on prefix
  50.     update(maxDif, S, 0 - D*S);
  51.     updateR(maxP, S, 0);
  52.     for (int t = 0; t <= MAX_T+1; ++t) {
  53.         if (fairsOnDay[t].empty()) continue;
  54.         int c = fairsOnDay[t].size();
  55.         sort(fairsOnDay[t].begin(), fairsOnDay[t].end()); // sort by location
  56.  
  57.         vector<int> maxProfit(c, -INF); // after visiting this fair, without visiting any other fairs at time t
  58.         for (int i = 0; i < c; ++i) {
  59.             auto [l, m] = fairsOnDay[t][i];
  60.             // arrive from upstream
  61.             //  maximum over all k <= l of m + D(l-k) + p[k]
  62.             maxProfit[i] = max(maxProfit[i], m + D*l + getMax(maxDif, l)); // add max of (p[k] - D*k) on prefix
  63.  
  64.             // arrive from downstream
  65.             //  maximum over all k >= l of m + p[k]
  66.             maxProfit[i] = max(maxProfit[i], m + getMaxR(maxP, l)); // add max of p[k] on suffix
  67.         }
  68.  
  69.         // now consider moving between fairs on this day
  70.         vector<int> downstream(c), upstream(c); // moving downstream or upstream
  71.         for (int i = 0; i < c; ++i) {
  72.             downstream[i] = maxProfit[i];
  73.             if (i) {
  74.                 auto [l, m] = fairsOnDay[t][i];
  75.                 int l2 = fairsOnDay[t][i-1].first;
  76.                 downstream[i] = max(downstream[i], downstream[i-1] + D*(l-l2) + m);
  77.             }
  78.         }
  79.         for (int i = c-1; i >= 0; --i) {
  80.             upstream[i] = maxProfit[i];
  81.             if (i < c-1) {
  82.                 int m = fairsOnDay[t][i].second;
  83.                 upstream[i] = max(upstream[i], upstream[i+1] + m);
  84.             }
  85.         }
  86.         for (int i = 0; i < c; ++i) maxProfit[i] = max({maxProfit[i], downstream[i], upstream[i]});
  87.  
  88.         if (t == MAX_T+1) cout << maxProfit[0] << endl;
  89.         else { // update data structures
  90.             for (int i = 0; i < c; ++i) {
  91.                 auto [l, m] = fairsOnDay[t][i];
  92.                 update(maxDif, l, maxProfit[i] - D*l);
  93.                 updateR(maxP, l, maxProfit[i]);
  94.             }
  95.         }
  96.     }
  97.     return 0;
  98. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement