题目链接
Codeforces Round 973 (Div. 2) D题 Minimize the Difference
思路
想要求出 m a x ( a 1 , a 2 , . . . , a n ) − m i n ( a 1 , a 2 , . . . , a n ) max(a_{1},a_{2},...,a_{n}) - min(a_{1},a_{2},...,a_{n}) max(a1,a2,...,an)−min(a1,a2,...,an)的最小值,实际上就是要求最大值的最小值和最小值的最大值。
根据题目要求,我们发现前面的数可以任意小,后面的数可以任意大。因此,最大值和最小值是具有单调性的。
我们直接二分最大值和最小值即可。
代码
#pragma GCC optimize("O2")
#pragma GCC optimize("O3")
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define debug() cout<<"-------------------"<<endl;
typedef long long i64;
typedef unsigned long long u64;
typedef pair<int, int> pii;
const int N = 2e5 + 5, M = 1e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
std::mt19937 rnd(time(0));
int n;
int a[N];
void solve()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
int low = 0, high = 1e12;
//算最大值的最小值
while (low < high)
{
int mid = low + high >> 1;
auto check1 = [&](auto check1, int x)->bool{
vector<int>v(n + 1);
for (int i = 1; i <= n; i++)
v[i] = a[i];
for (int i = 1; i <= n; i++)
{
if (v[i] > x && i < n)
{
v[i + 1] += (v[i] - x);
v[i] = x;
}
}
return v[n] <= x;
};
if (check1(check1, mid))
{
high = mid;
}
else low = mid + 1;
}
int ans1 = high;
low = 0, high = 1e12;
//算最小值的最大值
while (low < high)
{
int mid = low + high + 1 >> 1;
auto check2 = [&](auto check2, int x)->bool{
vector<int>v(n + 1);
for (int i = 1; i <= n; i++)
v[i] = a[i];
for (int i = n; i >= 1; i--)
{
if (v[i] < x && i > 1)
{
v[i - 1] -= (x - v[i]);
v[i] = x;
}
}
return v[1] >= x;
};
if (check2(check2, mid))
{
low = mid;
}
else high = mid - 1;
}
int ans2 = low;
cout << ans1 - ans2 << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int test = 1;
cin >> test;
for (int i = 1; i <= test; i++)
{
solve();
}
return 0;
}