Advertisement
erek1e

IOI '15 P4 - Horses (Standard I/O)

Jul 6th, 2023
883
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.60 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <set>
  5. #include <tuple>
  6.  
  7. using namespace std;
  8.  
  9. const int MAX_Y = 2e9;
  10.  
  11. struct Segment {
  12.     int l, r, bestV, bestI;
  13.     Segment() {}
  14.     Segment(int left, int right, int v, int i): l(left), r(right), bestV(v), bestI(i) {}
  15.     bool operator < (const Segment &s2) const {
  16.         return pair<int, int>(l, r) < pair<int, int>(s2.l, s2.r);
  17.     }
  18. };
  19.  
  20. // Modular arithmetic
  21. const int BASE = 1e9 + 7;
  22. int add(int x, int y) {
  23.     x += y;
  24.     if (x >= BASE) return x-BASE;
  25.     return x;
  26. }
  27. int mult(int x, int y) {
  28.     return (long long)x*y % BASE;
  29. }
  30.  
  31. // Segment Tree on range product over X and range max over Y
  32. class Node {
  33. private:
  34.     int xProduct = 1, yMax = 0, yMaxI = -1;
  35.     Node * left, * right;
  36. public:
  37.     // all ranges [)
  38.     void update(int l, int r, int i, int x, int y) {
  39.         if (l+1 == r) {
  40.             xProduct = x, yMax = y, yMaxI = l;
  41.             return;
  42.         }
  43.         if (!left) left = new Node();
  44.         if (!right) right = new Node();
  45.  
  46.         int mid = (l + r) / 2;
  47.         if (i < mid) left->update(l, mid, i, x, y);
  48.         else right->update(mid, r, i, x, y);
  49.         xProduct = mult(left->xProduct, right->xProduct);
  50.         tie(yMax, yMaxI) = max(pair<int, int>{left->yMax, left->yMaxI}, pair<int, int>{right->yMax, right->yMaxI});
  51.     }
  52.     pair<int, pair<int, int>> rangeQuery(int l, int r, int ql, int qr) {
  53.         if (r <= ql || qr <= l) return {1, {0, -1}};
  54.         else if (ql <= l && r <= qr) return {xProduct, {yMax, yMaxI}};
  55.         else {
  56.             int mid = (l + r) / 2;
  57.             pair<int, pair<int, int>> pr1{1, {0, -1}}, pr2{1, {0, -1}};
  58.             if (left) pr1 = left->rangeQuery(l, mid, ql, qr);
  59.             if (right) pr2 = right->rangeQuery(mid, r, ql, qr);
  60.             return {mult(pr1.first, pr2.first), max(pr1.second, pr2.second)};
  61.         }
  62.     }
  63. };
  64.  
  65. int main() {
  66.     ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  67.     int n; cin >> n;
  68.     vector<int> X(n), Y(n);
  69.     for (int &x : X) cin >> x;
  70.     for (int &y : Y) cin >> y;
  71.  
  72.     Node * root = new Node(); // segment tree
  73.     for (int i = 0; i < n; ++i) root->update(0, n, i, X[i], Y[i]);
  74.  
  75.     set<Segment> segments; // of equal multiplier
  76.     auto createSegment = [&](int l, int r) {
  77.         auto res = root->rangeQuery(0, n, l, r+1);
  78.         segments.emplace(l, r, res.second.first, res.second.second);
  79.     };
  80.     for (int i = 0, start = 0; i < n; ++i) {
  81.         if (i == n-1 || X[i+1] > 1) {
  82.             createSegment(start, i);
  83.             start = i+1;
  84.         }
  85.     }
  86.  
  87.     auto maxProfit = [&]() {
  88.         int best = n, bestVal = 0, bestCoefficient = 1;
  89.         int coefficient = 1;
  90.         for (set<Segment>::reverse_iterator it = segments.rbegin(); it != segments.rend(); ++it) {
  91.             int val = it->bestV, i = it->bestI;
  92.             if (best == n || (long long)val * bestCoefficient > (long long)bestVal * coefficient) {
  93.                 best = i, bestVal = val, bestCoefficient = coefficient;
  94.             }
  95.             int x = X[it->l];
  96.             if ((long long)coefficient * x > MAX_Y) break;
  97.             coefficient *= x;
  98.         }
  99.         // prefix product of x[i] up to best multiplied by Y[best]
  100.         auto res = root->rangeQuery(0, n, 0, best+1);
  101.         return mult(res.first, Y[best]);
  102.     };
  103.  
  104.     cout << maxProfit() << '\n';
  105.     int m; cin >> m;
  106.     while (m--) {
  107.         int type, pos, val;
  108.         cin >> type >> pos >> val;
  109.         bool wasSegmentStart = X[pos] > 1;
  110.         if (type == 1) X[pos] = val;
  111.         else Y[pos] = val;
  112.         root->update(0, n, pos, X[pos], Y[pos]);
  113.         bool isSegmentStart = X[pos] > 1;
  114.        
  115.         auto it = segments.upper_bound({pos, n+1, 0, 0});
  116.         --it;
  117.        
  118.         if (pos != 0 && wasSegmentStart != isSegmentStart) {
  119.             // must update segments
  120.             if (wasSegmentStart) {
  121.                 // merge segments it and prev(it)
  122.                 int r = it->r;
  123.                 it = prev(segments.erase(it));
  124.                 int l = it->l;
  125.                 segments.erase(it);
  126.                 createSegment(l, r);
  127.             } else {
  128.                 // split segment it
  129.                 int l = it->l, r = it->r;
  130.                 segments.erase(it);
  131.                 createSegment(l, pos-1);
  132.                 createSegment(pos, r);
  133.             }
  134.         } else {
  135.             // still need to update the segments' max Y
  136.             int l = it->l, r = it->r;
  137.             segments.erase(it);
  138.             createSegment(l, r);
  139.         }
  140.         cout << maxProfit() << '\n';
  141.     }
  142.     return 0;
  143. }
  144.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement