# Binary Search# Prefix Sum# Greedy

b310 - 英靈召喚

🔗 前往 ZeroJudge 原題

題目描述

題目要求找出蒐集到所需魔力 m 的最短連續時間。給定 n 秒內大地釋放的魔力量 a[i],需要找到一個連續的時間段,使得該時間段內蒐集到的魔力總和大於等於 m。如果 n 秒內無法蒐集到足夠的魔力,則輸出 "GGGGGZ"。

解題思路

本題可以使用二分搜尋法來解決。首先,計算所有魔力的總和,如果總和小於所需魔力 m,則直接輸出 "GGGGGZ"。否則,使用二分搜尋來尋找最短的連續時間。

二分搜尋的範圍是 [0, n]。對於每個中間值 t,使用一個迴圈來計算從 0n-1 秒,長度為 2*t+1 的時間段內蒐集到的魔力總和。具體來說,迴圈中計算從 ii+t 的魔力總和,並檢查是否大於等於 m。如果存在一個時間段滿足條件,則更新右邊界為 mid-1,否則更新左邊界為 mid+1

使用 prefix sum 的概念可以優化計算時間段內魔力總和的過程。

複雜度分析

  • 時間複雜度: O(n log n)
  • 空間複雜度: O(n)

程式碼

#include <iostream>
using namespace std;
long long int a[1000001],m,n,total;
bool judge(int t){
	long long int tmp=0;
	for(int i=0,j=-t;i<n;++i,++j){
		tmp+=a[i];
		if(j>=0)tmp-=a[j];
		if(tmp>=m)return 1;
	}
	return 0;
}
int bs(int l,int r){
	if(r<l)return l;
	int mid=(l+r)/2;
	if(judge(mid))
		return bs(l,mid-1);
	else
		return bs(mid+1,r);
}
int main(){
	cin.tie(0); ios::sync_with_stdio(false);
	cin >> n >> m;
	for(int i=0;i<n;++i){
		cin >> a[i];
		total+=a[i];
	}
	if(total<m)
		cout << "GGGGGZ";
	else
		cout << bs(0,n);
}

Discussion