CF1623CBalanced Stone Heaps 题解

11 篇文章 0 订阅
2 篇文章 0 订阅

题目描述:

你有 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 i1 堆石子里放入 d d d 粒石子,往第 i − 2 i-2 i2 堆石子里放入 2 d 2d 2d 粒石子。
你需要通过合理设计操作方案,使得数量最少的一堆石子的数量最大。请求出这个最大值。
数据范围:

  • t t t 组数据, 1 ⩽ t ⩽ 2 × 1 0 5 1\leqslant t\leqslant 2\times 10^5 1t2×105
  • 3 ⩽ n , ∑ n ⩽ 2 × 1 0 5 3\leqslant n,\sum n\leqslant 2\times 10^5 3n,n2×105
  • 1 ⩽ h i ⩽ 1 0 9 1\leqslant h_i\leqslant 10^9 1hi109

样例输入输出:

输入
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[i2]只能给 ( h [ i ] − m i d ) / 3 ∗ 2 (h[i] - mid) / 3 * 2 (h[i]mid)/32 h [ i − 1 ] h[i-1] h[i1]只能给 ( 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值