Minimize the Difference§

二分 + 贪心。

二分最大的最小值,之后再二分最小的最大值。

前者比较简单,而后者需要贪心的构造,具体思路看下方代码。

#ifndef CAIKI_LOCAL
#include <bits/stdc++.h>
#endif

#ifdef CAIKI_LOCAL
#include <iostream>
#include <vector>

auto _ = []() {
    freopen("../io/in.txt", "r", stdin);
    freopen("../io/out.txt", "w", stdout);
    return true;
}();

#endif

#define int long long

void solve() {
    int n;
    std::cin >> n;

    std::vector<int> a(n);
    for (auto &it : a) {
        std::cin >> it;
    }

    auto check1 = [&](int u) -> bool {
        int x = 0;
        for (auto it : a) {
            if (it > u) {
                x += it - u;
            } else {
                x -= u - it;
                if (x < 0) {
                    return false;
                }
            }
        }

        return true;
    };

    int l = 0, r = 1e18;
    while (l < r) {
        int mid = (l + r + 1) >> 1;
        if (check1(mid)) {
            l = mid;
        } else {
            r = mid - 1;
        }
    }

    int min = l;

    auto check2 = [&](int u) -> bool {
        int x = 0;
        std::vector<int> b(n + 1, 0), more(n + 1);

        for (int i = n - 1; i >= 0; i--) {
            b[i] = b[i + 1];
            if (a[i] < min) {
                b[i] += min - a[i];
            } else {
                more[i] = a[i] - min - std::min(b[i], a[i] - min);
                b[i] -= std::min(b[i], a[i] - min);
            }
        }

        for (int i = 0; i < n; i++) {
            x += more[i];
            x -= std::min(u - min, x);
        }

        return x == 0;
    };

    r = 1e18;
    while (l < r) {
        int mid = (l + r) >> 1;
        if (check2(mid)) {
            r = mid;
        } else {
            l = mid + 1;
        }
    }

    std::cout << l - min << '\n';
}

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int t;
    std::cin >> t;

    while (t--) {
        solve();
    }

    return 0;
}