蜡烛(gmoj)

题目描述

Jimmy有n支蜡烛。他把这些蜡烛排成了一排,从左往右的编号为1~n。经过无数次的实验后,他发现每支蜡烛有一个属性a[i],当第i支蜡烛左边(即第i-1支,当时的风向比较奇妙)的蜡烛被点亮后,经过a[i]的时间第i支蜡烛也会点亮。
Jimmy一开始先任意点m支蜡烛(不需要消耗时间),他想知道至少需要多少时间才能使得n支蜡烛全部被点亮。

输入

从文件 d.in 中读入数据。

第一行两个整数n,m。
第二行n个空格分开的整数a[i]。

输出

输出到文件 d.out 中。

一行一个整数表示所有蜡烛都亮的最小时间。

样例输入
5 3
1 2 2 1 5
样例输出
2
数据范围限制

对于20%的数据:n,m<=10。
对于50%的数据:n,m<=3000
对于100%的数据:1<=m<=n<=10^5,1<=a[i]<=10^9。

样例解释

点燃1、3、5根蜡烛,需要2的时间烧到第二根,1的时间烧到第四根,最小时间为2。


这题我们可以用二分进行一个最短时间的一个计算

Coding~~~

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 20;
int n, m;
int a[N], sum;
void dg(int l, int r) { /*枚举时间范围*/
	int mid = (l + r) / 2;
	int cnt = 1/*点燃的蜡烛的数量*/, t = 0/*目前最小时间*/;
	for (int i = 2; i <= n; i++) {
		t += a[i];//将时间+目前蜡烛点燃的时间
		if (t > mid) {//如果t大于目前的时间最小值,必须点燃这一个蜡烛
			if (cnt < m) cnt++, t = 0;//点蜡烛
			else {
				if (r == l) return ;//如果时间重合,返回上一层
				else if (l + 1 == r) dg(mid + 1, r);//防止mid卡循环,例:l=1,r=2,mid=1会卡死循
				else dg(mid, r);//没问题,继续分治
				return ;//返回
			}
		}
	}
	sum = mid;//将答案储存
	if (l == r)
		return ;//同上
	dg(l, mid - 1);//继续分治
}
main() {
	freopen("d.in", "r", stdin);
	freopen("d.out", "w", stdout);
	cin >> n/*蜡烛编号*/ >> m/*可以点亮m个蜡烛*/;
	for (int i = 1; i <= n; i++)
		cin >> a[i]/*输入*/, sum += a[i]/*使用sum进行计数*/;
	dg(1, sum - a[1]/*第一个蜡烛必点,所以sum-a[1]*/);
	cout << sum;
	return 0;
}

纪中原题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值