题目描述:
你有
n
n
n 堆石子,其中第
i
i
i 堆里面有
h
i
h_i
hi 粒石子。你需要从第
3
3
3 堆石子开始从前往后进行操作。设当前为第
i
i
i 堆石子,你可以选择一个在
[
0
,
h
i
3
]
[0,\frac {h_i}3]
[0,3hi] 的整数
d
d
d,从第
i
i
i 堆石子中取出
3
d
3d
3d 粒石子,然后往第
i
−
1
i-1
i−1 堆石子里放入
d
d
d 粒石子,往第
i
−
2
i-2
i−2 堆石子里放入
2
d
2d
2d 粒石子。
你需要通过合理设计操作方案,使得数量最少的一堆石子的数量最大。请求出这个最大值。
数据范围:
- t t t 组数据, 1 ⩽ t ⩽ 2 × 1 0 5 1\leqslant t\leqslant 2\times 10^5 1⩽t⩽2×105。
- 3 ⩽ n , ∑ n ⩽ 2 × 1 0 5 3\leqslant n,\sum n\leqslant 2\times 10^5 3⩽n,∑n⩽2×105。
- 1 ⩽ h i ⩽ 1 0 9 1\leqslant h_i\leqslant 10^9 1⩽hi⩽109。
样例输入输出:
输入
4
4
1 2 10 100
4
100 100 100 1
5
5 1 1 1 8
6
1 2 3 4 5 6
输出
7
1
1
3
分析
二分+贪心。
二分
倒序操作。
为了让每一个数都在 m i d mid mid及以上,所以 h [ i − 2 ] h[i-2] h[i−2]只能给 ( h [ i ] − m i d ) / 3 ∗ 2 (h[i] - mid) / 3 * 2 (h[i]−mid)/3∗2, h [ i − 1 ] h[i-1] h[i−1]只能给 ( h [ i ] − m i d ) / 3 (h[i] - mid) / 3 (h[i]−mid)/3。或者。因为有的数会小于3所以有些要用无操作的数组给。
code
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 100;
int n, mid;
int h[N], h1[N];
bool check()
{
int re = 0;
for (int i = 1; i <= n; i++) h1[i] = h[i];
for (int i = n; i >= 3; i--)
{
if(h1[i] >= mid)
{
h1[i - 1] += min(h[i], h1[i] - mid) / 3, h1[i - 2] += min(h[i], h1[i] - mid) / 3 * 2;
}
else re = 1;
}
if (h1[1] < mid || h1[2] < mid) re = 1;
return !re;
}
int main()
{
int T;
cin >> T;
while (T--)
{
int ans;
cin >> n;
for (int i = 1; i <= n; i++) cin >> h[i];
int l = 1, r = 2e9;
while (l <= r)
{
mid = (l + r) / 2;
if (check())
{
l = mid + 1;
ans = mid;
}
else r = mid - 1;
}
cout << ans << endl;
}
return 0;
}