Advertisement
libobil

Untitled

Jan 12th, 2023
790
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.72 KB | None | 0 0
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <numeric>
  4. #include <cassert>
  5. #include <vector>
  6. #include <stack>
  7. #include <queue>
  8. #include <set>
  9.  
  10. typedef long long llong;
  11. const int MAXN = 1000000 + 10;
  12. const int INF  = 1e9 + 1;
  13.  
  14. struct Interval
  15. {
  16.     int l, r, value;
  17.     int toReach;
  18.  
  19.     Interval(){}
  20.     Interval(int _l, int _r, int _value, int _toReach)
  21.     {
  22.         l = _l;
  23.         r = _r;
  24.         value = _value;
  25.         toReach = _toReach;
  26.     }
  27.  
  28.     inline bool friend operator < (const Interval &a, const Interval &b)
  29.     {
  30.         return a.r - a.l < b.r - b.l || (a.r - a.l == b.r - b.l && a.l < b.l);
  31.     }
  32.  
  33.     inline bool friend operator == (const Interval &a, const Interval &b)
  34.     {
  35.         return a.l == b.l && a.r == b.r && a.value == b.value;
  36.     }
  37. };
  38.  
  39. int sz[MAXN];
  40. int par[MAXN];
  41. int dep[MAXN];
  42. int height[MAXN];
  43.  
  44. int find(int node)
  45. {
  46.     if (par[node] == node) return node;
  47.     return par[node] = find(par[node]);
  48. }
  49.  
  50. inline void merge(int x, int y)
  51. {
  52.     x = find(x);
  53.     y = find(y);
  54.     if (dep[x] > dep[y]) std::swap(x, y);
  55.     if (dep[x] == dep[y]) dep[y]++;
  56.  
  57.     par[x] = y;
  58.     sz[y] += sz[x];
  59.     height[y] = std::max(height[x], height[y]);
  60. }
  61.  
  62. inline int getHeight(int x)
  63. {
  64.     return height[find(x)];
  65. }
  66.  
  67. int n;
  68. llong k;
  69. int a[MAXN];
  70. int prev[MAXN];
  71. int next[MAXN];
  72. std::stack <int> st;
  73. std::vector <Interval> bySize[MAXN];
  74. std::vector <Interval> sorted;
  75. void solve()
  76. {
  77.     bool good = true;
  78.     for (int i = 1 ; i <= n - 1 && good ; ++i)
  79.     {
  80.         good &= (a[i] == a[i + 1]);
  81.     }
  82.  
  83.     if (good)
  84.     {
  85.         std::cout << 0 << '\n';
  86.         return;
  87.     }
  88.  
  89.     std::iota(par + 1, par + 1 + n, 1);
  90.     std::fill(dep + 1, dep + 1 + n, 1);
  91.     std::fill(sz + 1, sz + 1 + n, 1);
  92.     for (int i = 1 ; i <= n ; ++i)
  93.     {
  94.         height[i] = a[i];
  95.     }
  96.  
  97.     a[0] = INF;
  98.     llong ans = 0;
  99.     while (!st.empty()) st.pop(); st.push(0);
  100.     for (int i = 1 ; i <= n ; ++i)
  101.     {
  102.         if (i != 1) ans += abs(a[i] - a[i - 1]);
  103.         while (!st.empty() && a[st.top()] <= a[i])
  104.         {
  105.             st.pop();
  106.         }
  107.  
  108.         prev[i] = st.top();
  109.         st.push(i);
  110.     }
  111.  
  112.     while (!st.empty()) st.pop(); st.push(0);
  113.     for (int i = n ; i >= 1 ; --i)
  114.     {
  115.         while (!st.empty() && a[st.top()] < a[i])
  116.         {
  117.             st.pop();
  118.         }
  119.  
  120.         next[i] = st.top();
  121.         st.push(i);
  122.     }
  123.  
  124.     int cntIntervals = 0;
  125.     for (int i = 1 ; i <= n ; ++i)
  126.     {
  127.         if (prev[i] != 0 && next[i] != 0 && a[next[i]] > a[i])
  128.         {
  129.             bySize[next[i] - prev[i] - 1].push_back({prev[i] + 1, next[i] - 1, a[i], std::min(a[prev[i]], a[next[i]])});
  130.             cntIntervals++;
  131.         }
  132.     }
  133.  
  134.     sorted.reserve(cntIntervals);
  135.     for (int i = 1 ; i <= n ; ++i)
  136.     {
  137.         for (const Interval &curr : bySize[i])
  138.         {
  139.             sorted.push_back(curr);
  140.         }
  141.     }
  142.  
  143.     int last = 1;
  144.     for (int i = 2 ; i <= n ; ++i)
  145.     {
  146.         if (a[last] != a[i])
  147.         {
  148.             last = i;
  149.         } else
  150.         {
  151.             merge(last, i);
  152.         }
  153.     }
  154.  
  155.     int ptr = 0;
  156.     int lastLen = 1;
  157.     int firstLen = 1;
  158.     int lastHeight = a[n];
  159.     int firstHeight = a[1];
  160.     bool readyToBreak = false;
  161.     while (sz[find(1)] != n)
  162.     {
  163.         lastLen = sz[find(n)];
  164.         firstLen = sz[find(1)];
  165.         bool isLastGood = (getHeight(n - lastLen) > lastHeight);
  166.         bool isFirstGood = (getHeight(firstLen + 1) > firstHeight);
  167.  
  168.         if (isFirstGood && (!isLastGood || firstLen < lastLen))
  169.         {
  170.             if (getHeight(firstLen + 1) - firstHeight >= 2 && (readyToBreak || ptr == sorted.size() || sorted[ptr].r - sorted[ptr].l + 1 > 2*firstLen))
  171.             {
  172.                 int toAdd = std::min(k / firstLen, (llong)getHeight(firstLen + 1) - firstHeight - 1);
  173.                 ans -= toAdd;
  174.                 k -= 1LL * firstLen * toAdd;
  175.                 height[find(1)] += toAdd;
  176.                 firstHeight += toAdd;
  177.                 if ((llong)getHeight(firstLen + 1) - firstHeight != 1) break;
  178.                 continue;
  179.             }
  180.  
  181.             int afterFirst = sz[find(firstLen + 1)];
  182.             int secondLen = INF;
  183.             if (isLastGood) secondLen = lastLen;
  184.             if (firstLen + afterFirst + 1 <= n && getHeight(firstLen + afterFirst + 1) > getHeight(firstLen + 1)) secondLen = std::min(secondLen, firstLen + afterFirst);
  185.             if (getHeight(firstLen + 1) - firstHeight == 1 && (readyToBreak || ptr == sorted.size() || firstLen + secondLen < sorted[ptr].r - sorted[ptr].l + 1))
  186.             {
  187.                 int toAdd = std::min(k / firstLen, (llong)getHeight(firstLen + 1) - firstHeight);
  188.                 ans -= toAdd;
  189.                 k -= 1LL * firstLen * toAdd;
  190.                 if (toAdd != (llong)getHeight(firstLen + 1) - firstHeight) break;
  191.                 merge(1, firstLen + 1);
  192.                 firstHeight++;
  193.                 continue;
  194.             }
  195.         }
  196.  
  197.         if (isLastGood)
  198.         {
  199.             if (getHeight(n - lastLen) - lastHeight >= 2 && (readyToBreak || ptr == sorted.size() || sorted[ptr].r - sorted[ptr].l + 1 > 2*lastLen))
  200.             {
  201.                 int toAdd = std::min(k / lastLen, (llong)getHeight(n - lastLen) - lastHeight - 1);
  202.                 ans -= toAdd;
  203.                 k -= 1LL * lastLen * toAdd;
  204.                 height[find(n)] += toAdd;
  205.                 lastHeight += toAdd;
  206.                 if ((llong)getHeight(n - lastLen) - lastHeight != 1) break;
  207.                 continue;
  208.             }
  209.  
  210.             int beforeLast = sz[find(n - lastLen)];
  211.             int secondLen = INF;
  212.             if (isFirstGood) secondLen = firstLen;
  213.             if (n - lastLen - beforeLast >= 1 && getHeight(n - lastLen - beforeLast) > getHeight(n - lastLen)) secondLen = std::min(secondLen, beforeLast + lastLen);
  214.             if (getHeight(n - lastLen) - lastHeight == 1 && (readyToBreak || ptr == sorted.size() || lastLen + secondLen < sorted[ptr].r - sorted[ptr].l + 1))
  215.             {
  216.                 int toAdd = std::min(k / lastLen, (llong)getHeight(n - lastLen) - lastHeight);
  217.                 ans -= toAdd;
  218.                 k -= 1LL * lastLen * toAdd;
  219.                 if (toAdd != (llong)getHeight(n - lastLen) - lastHeight) break;
  220.                 merge(n - lastLen, n);
  221.                 lastHeight++;
  222.                 continue;
  223.             }
  224.         }
  225.  
  226.         if (ptr == cntIntervals)
  227.         {
  228.             break;
  229.         }
  230.        
  231.         Interval curr = sorted[ptr++];
  232.         int toAdd = std::min((llong)curr.toReach - curr.value, k / (curr.r - curr.l + 1));
  233.         k -= 1LL * (curr.r - curr.l + 1) * toAdd;
  234.         ans -= 2 * toAdd;
  235.         height[find(curr.l)] += toAdd;
  236.  
  237.         if (getHeight(curr.l - 1) == curr.value + toAdd)
  238.         {
  239.             merge(curr.l - 1, curr.l);
  240.         }
  241.  
  242.         if (getHeight(curr.r + 1) == curr.value + toAdd)
  243.         {
  244.             merge(curr.r, curr.r + 1);
  245.         }
  246.  
  247.         if (toAdd != curr.toReach - curr.value)
  248.         {
  249.             if (readyToBreak) break;
  250.             readyToBreak = true;
  251.             ptr--;
  252.         }
  253.     }
  254.  
  255.     std::cout << ans << '\n';
  256. }
  257.  
  258. void reset()
  259. {
  260.     while (!st.empty()) st.pop();
  261.     for (int i = 1 ; i <= n ; ++i)
  262.     {
  263.         bySize[i].clear();
  264.         next[i] = prev[i] = 0;
  265.     }
  266.  
  267.     sorted.clear();
  268. }
  269.  
  270. void read()
  271. {
  272.     std::cin >> n >> k;
  273.     for (int i = 1 ; i <= n ; ++i)
  274.     {
  275.         std::cin >> a[i];
  276.     }
  277. }
  278.  
  279. void fastIO()
  280. {
  281.     std::ios_base :: sync_with_stdio(0);
  282.     std::cout.tie(nullptr);
  283.     std::cin.tie(nullptr);
  284. }
  285.  
  286. int tests;
  287. int main()
  288. {
  289.     fastIO();
  290.     std::cin >> tests;
  291.  
  292.     while (tests--)
  293.     {
  294.         reset();
  295.         read();
  296.         solve();
  297.     }
  298.  
  299.     return 0;
  300. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement