Codeforces Round #547 (Div. 3) E. Superhero Battle(二分)

E. Superhero Battle
time limit per test 2 seconds
memory limit per test 256 megabytes
inputstandard input
outputstandard output

A superhero fights with a monster. The battle consists of rounds, each of which lasts exactly n minutes. After a round ends, the next round starts immediately. This is repeated over and over again.

Each round has the same scenario. It is described by a sequence of n numbers: d1,d2,…,dn (− 1 0 6 10^6 106≤di≤ 1 0 6 10^6 106). The i-th element means that monster’s hp (hit points) changes by the value di during the i-th minute of each round. Formally, if before the i-th minute of a round the monster’s hp is h, then after the i-th minute it changes to h:=h+di.

The monster’s initial hp is H. It means that before the battle the monster has H hit points. Print the first minute after which the monster dies. The monster dies if its hp is less than or equal to 0. Print -1 if the battle continues infinitely.

Input
The first line contains two integers H and n (1≤H≤ 1 0 1 2 10^12 1012, 1≤n≤ 2 ⋅ 1 0 5 2⋅10^5 2105). The second line contains the sequence of integers d1,d2,…,dn ( − 1 0 6 ≤ d i ≤ 1 0 6 −10^6≤di≤10^6 106di106), where di is the value to change monster’s hp in the i-th minute of a round.

Output
Print -1 if the superhero can’t kill the monster and the battle will last infinitely. Otherwise, print the positive integer k such that k is the first minute after which the monster is dead.

Examples

1000 6
-100 -200 -300 125 77 -4
9
1000000000000 5
-1 0 0 0 0
4999999999996
10 4
-3 -6 5 4
-1
题目大意:

给定一个初始高度 H H H,每轮(round)下降需要 n n n分钟,问下降后高度最先小于等于0的时间。

思路:

对于每一轮下降,利用前缀和求出这一轮最后下降多少;因为这一轮下降过程中间可能小球的高度可能小于等于零,所以用 m n mn mn记录这一轮小球最多下降多少。
然后统计小球的下降轮数,因为小球下降轮数越少越安全,所以用二分统计最多可能的下降轮数。然后统计所有时间即可。

#include
#define int long long 
using namespace std;
int n,h[200005],H;
int sum[200005];
int mn=0x3f3f3f3f,num=0;
int judge(int mid){//二分统计下降轮数,下降轮数越少越安全
	if(H+mid*sum[n]>abs(mn)) return 1;
	else return 0; 
} 
signed main(){//防止爆int
	cin>>H>>n;
	
	for(int i=1;i<=n;i++) cin>>h[i],sum[i]=sum[i-1]+h[i],mn=min(mn,sum[i]);//前缀和统计从最开始的地方在第i次后下降的位置
	if(sum[n]>=0&&H+mn>0){cout<<"-1\n";return 0;}
	int round=0;
	
	if(H+mn>0){
		num=H/abs(sum[n]);
		int l=1,r=num;
		while(l<r){//二分求下降轮数
			int mid=(l+r)>>1;
			if(judge(mid)) l=mid+1;
			else r=mid;
		}
		round=l;
	} 
	int rest=H-round*abs(sum[n]),ans=0;
	ans+=round*n;
	
	for(int i=1;i<=n;i++){
		if(rest+sum[i]<=0){
			ans+=i;
			break;
		}
	}
	cout<<ans<<"\n";
	return 0;
}

你可能感兴趣的:(Codeforces Round #547 (Div. 3) E. Superhero Battle(二分))