Codeforces 551C GukiZ hates Boxes 二分答案

題目鏈接

題意:

 一共有n個空地(是一個數軸,從x=1 到 x=n),每個空地上有a[i]塊石頭
 有m個學生
 目標是刪除所有石頭
 一開始所有學生都站在 x=0的地方
 每秒鐘每個學生都可以在原地刪除一塊石頭,或者向 → 移動一格距離
 問:刪除所有石頭的最短時間

案例解析:
 3 2 
1 0 2

 第一個學生第一秒向→走,第二秒刪a[1]的一塊石頭
 第二個學生一直走到頭,刪掉a[3] ,所以第二個學生花費是 1+1+1+2 = 5
兩個學生可以同時運動。

思路:

二分答案,設答案爲x,即需要x秒來搬完石頭

 先拿一個學生來
 總要有一個學生來搬最遠的那堆石頭的
先讓這個學生走到盡頭

 這個學生擁有的時間就是x
 那麼走到盡頭後,還剩下的時間用來搬最後一堆石頭
 如果這堆石頭搬不完,那麼這個學生就利用完了,換一個學生
 如果搬的完  那麼這個學生還剩下的時間可以用來搬前一堆石頭 一直把這個學生利用完。
 
如果所有學生都利用完了石頭還是搬不完,那麼x秒肯定是不夠的
 否則x秒就是夠的

#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <cstdio>
#include <map>
#include <queue>
#include <algorithm>
#include <stack>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
using namespace std;
template <class T>
inline bool rd(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
template <class T>
inline void pt(T x) {
	if (x < 0) {
		putchar('-');
		x = -x;
	}
	if (x > 9) pt(x / 10);
	putchar(x % 10 + '0');
}
typedef long long ll;
typedef pair<ll, ll> pii;
const int inf = 1e9;
const int N = 1e5 + 10;
int n, m;
int a[N], b[N];
bool ok(ll x) {
	for (int i = 1; i <= n; i++)b[i] = a[i];
	int top = n, tmp = m;
	while (tmp-->0 && top) {
		ll lef = x - top;
		while (lef && top) {
			if (b[top] == 0) { top--;continue; }
			if (b[top] <= lef) {
				lef -= b[top--];
			}
			else { b[top] -= (int)lef;lef = 0; }
		}
	}
	while (top && b[top] == 0)top--;//找到最後一個並且不是0的點
	return top == 0;
}
int main() {
	rd(n); rd(m);
	int d = 1;
	for (int i = 1; i <= n; i++) {
		rd(a[i]);
	}
	while (a[n] == 0)n--; //把最後的0刪掉
	ll l = 1, r = 1e15, ans;
	while (l <= r) {
		ll mid = (l + r) >> 1;
		if (ok(mid)) {
			ans = mid;
			r = mid - 1;
		}
		else l = mid + 1;
	}
	pt(ans);
	return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章