danielvitor23

D. Beautiful decrease

Jul 15th, 2024
231
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.86 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. #ifdef ENABLE_DEBUG
  3.   #define DEBUG(x) std::cout << x << std::endl
  4. #else
  5.   #define DEBUG(x)
  6. #endif
  7. #define fi first
  8. #define se second
  9. #define pb push_back
  10. #define all(x) x.begin(),x.end()
  11. #define rall(x) x.rbegin(),x.rend()
  12. using namespace std;
  13. using ii = pair<int, int>;
  14. using iii = tuple<int, int, int>;
  15. using i64 = long long;
  16. const int INF = 0x3f3f3f3f;
  17. const i64 INFLL = 0x3f3f3f3f3f3f3f3fLL;
  18. const int MAXN = 1e5+5;
  19.  
  20. template<class T>
  21. class SegmentTreeLazy {
  22.     struct Node {
  23.     int idx;
  24.         T val;
  25.         Node(T x, int idx) : val(x), idx(idx) {}
  26.         Node () : val(INFLL), idx(INF) {}
  27.     };
  28.     int N;
  29.     std::vector<T> a, lazy;
  30.     std::vector<Node> tr;
  31.     Node neutral;
  32.     inline Node join(const Node &a, const Node &b) {
  33.     if (a.val < b.val) return Node(a.val, a.idx);
  34.     return Node(b.val, b.idx);
  35.     }
  36.     inline void upLazy(int node, int l, int r) {
  37.         if (lazy[node] == 0) return;
  38.         tr[node].val += lazy[node];
  39.         int lc = (node << 1);
  40.         (l != r ? lazy[lc] += lazy[node], lazy[lc+1] += lazy[node] : 0);
  41.         lazy[node] = 0;
  42.     }
  43.     void build(int node, int l, int r) {
  44.         if (l == r) tr[node] = Node(a[l], l);
  45.         else {
  46.             int mid = l+(r-l)/2, lc = (node << 1);
  47.             build(lc, l, mid);
  48.             build(lc+1, mid+1, r);
  49.             tr[node] = join(tr[lc], tr[lc+1]);
  50.         }
  51.     }
  52.     void update(int node, int l, int r, int ul, int ur, T x) {
  53.         upLazy(node, l, r);
  54.         if (r < r or ur < ul or ur < l or r < ul) return;
  55.         if (ul <= l and r <= ur) {
  56.             lazy[node] += x;
  57.             upLazy(node, l, r);
  58.         } else {
  59.             int mid = l+(r-l)/2, lc = (node << 1);
  60.             update(lc, l, mid, ul, std::min(ur, mid), x);
  61.             update(lc+1, mid+1, r, std::max(mid+1, ul), ur, x);
  62.             tr[node] = join(tr[lc], tr[lc+1]);
  63.         }
  64.     }
  65.     Node query(int node, int l, int r, int ql, int qr) {
  66.         upLazy(node, l, r);
  67.         if (r < l or qr < ql or qr < l or r < ql) return neutral;
  68.         if (ql <= l and r <= qr) return tr[node];
  69.         int mid = l+(r-l)/2, lc = (node << 1);
  70.         return join(query(lc, l, mid, ql, std::min(qr, mid)),
  71.                     query(lc+1, mid+1, r, std::max(mid+1, ql), qr));
  72.     }
  73. public:
  74.     template<class MyIterator>
  75.     SegmentTreeLazy (MyIterator begin, MyIterator end) {
  76.         N = end-begin-1;
  77.         tr.assign(4*N, Node(INFLL, INF));
  78.         lazy.assign(4*N, 0);
  79.         a = std::vector<T>(begin, end);
  80.         build(1, 1, N);
  81.     }
  82.     SegmentTreeLazy (int n) : N(n) {
  83.         tr.assign(4*N, Node(INFLL, n));
  84.         lazy.assign(4*N, 0);
  85.         a.assign(N+1, 0);
  86.     }
  87.     pair<T, int> query(int l, int r) {
  88.     Node res = query(1, 1, N, l, r);
  89.         return ii(res.val, res.idx);
  90.     }
  91.     void update(int l, int r, T x) {
  92.         update(1, 1, N, l, r, x);
  93.     }
  94. };
  95.  
  96. int k;
  97.  
  98. class Compare {
  99.   public:
  100.   bool operator()(iii a, iii b) {
  101.     auto [l1, r1, mn1] = a;
  102.     auto [l2, r2, mn2] = b;
  103.  
  104.     i64 s1 = 1LL * (r1 - l1 + 1) * min(mn1, k);
  105.     i64 s2 = 1LL * (r2 - l2 + 1) * min(mn2, k);
  106.  
  107.     if (s1 == s2) {
  108.       return (r1 - l1 + 1) < (r2 - l2 + 1);
  109.     }
  110.  
  111.     return s1 < s2;
  112.   }
  113. };
  114.  
  115. int main() {
  116.   cin.tie(0)->sync_with_stdio(0);
  117.  
  118.   int n, q;
  119.   cin >> n >> q;
  120.  
  121.   i64 currSum = 0;
  122.   vector<i64> b{0};
  123.  
  124.   for (int i = 0; i < n; ++i) {
  125.     int x;
  126.     cin >> x;
  127.     b.pb(x);
  128.     currSum += x;
  129.   }
  130.  
  131.   SegmentTreeLazy<i64> ST(b.begin(), b.end());
  132.   priority_queue<iii, vector<iii>, Compare> pq;
  133.  
  134.   auto get_range = [&](auto&& get_range, int l, int r) {
  135.     if (r < l) return;
  136.     auto [val, idx] = ST.query(l, r);
  137.     if (val == 0) {
  138.       get_range(get_range, l, idx-1);
  139.       get_range(get_range, idx+1, r);
  140.       return;
  141.     }
  142.     if (val > 0) {
  143.       pq.push({ l, r, val });
  144.     }
  145.   };
  146.  
  147.   pq.push({ 1, n, ST.query(1, n).fi });
  148.  
  149.   while (q--) {
  150.     cin >> k;
  151.     while (k > 0) {
  152.       if (pq.empty()) break;
  153.       auto [l, r, mn] = pq.top(); pq.pop();
  154.       int qtd = min(mn, k);
  155.       currSum -= 1LL * (r - l + 1) * qtd;
  156.       k -= qtd;
  157.       ST.update(l, r, -qtd);
  158.       get_range(get_range, l, r);
  159.     }
  160.     cout << currSum << '\n';
  161.   }
  162.  
  163. }
Advertisement
Add Comment
Please, Sign In to add comment