Rescue
Time Limit: 3 Seconds Memory Limit: 65536 KB
The princess is trapped in a magic place. In this place, there are N magic stones. In order to rescue the princess, you should destroy all the stones.
The N stones are in a straight line. We number them as s1, s2, … sn from left to right. Each stone has a magic strength m1, m2, … mn. You have a powerful skill that can do some damage to the stones. To release the skill, you should stand to the right of some stone (si). Then you throw a power ball towards left. Initially, this ball has a power of p. When it hits a stone, it will do some damage to the stone and its power will be decreased, and the ball will continue to fly left to the next stone if its power is still positive. Formally, if you stand to the right of si and the power ball’s initial power is p, then the ball will do Max(0, p - (i - j) * (i - j)) damage to sj, for each j <= i. So from this formula, we can see that the damage to stone sj is only determined by the initial power of the ball and the number of stones between si and sj.
A stone is destroyed if the accumulated damage you do is larger than its magic strength. Note that even if a stone is destroyed, it will not disappear; your magic ball will do damage to it and the power will be decreased by that stone. You are not strong enough so that you can release at most k magic balls. It will cost a lot of energy if the power of the magic ball is too high. So what is the minimum value of p with which you can destroy all the magic stones, with no more than k magic balls? You can choose where to release each magic ball as your will, and the power of the ball must be a positive integer.
Input
The first line is the number of cases T (T ≤ 100). For each case, the first line gives two integers n, k (1 ≤ n ≤ 50000, 1 ≤ k ≤ 100000). The second line are n integers, giving m1, m2, … mn (1 ≤ mi ≤ 109).
Output
Print minimum possible p in a line.
Sample Input
2
1 1
1
3 1
1 4 5
Sample Output
2
6
Author: HANG, Hang
Source: The 2010 ACM-ICPC Asia Chengdu Regional Contest
题目大意:
有一排石头,每个石头都有一个自己的血量,每次可以站在一个石头的位置上攻击左边的石头,攻击力为
p
,站在位置
解题思路:
首先很容易想到二分
p
,然后进行check。
对于check我们也比较容易想到:从左往右扫,根据之前的攻击算出当前石头的剩余血量,然后站在这里用最小的攻击次数把剩下的血打完,重复知道攻击完所有石头,统计总攻击次数是否小于等于
我们可以发现,一对位置的伤害衰减为
(i−j)2=i2−2ij+j2
,当
j
向左移动一个单位的时候,伤害衰减就变成了
AC代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <ctime>
#include <bitset>
using namespace std;
#define INF 0x3f3f3f3f3f3f3f3f
#define ULL unsigned long long
#define LL long long
#define fi first
#define se second
#define mem(a, b) memset((a),(b),sizeof(a))
#define sqr(x) ((x)*(x))
const int MAXN=50000+3;
int N, K, hp[MAXN];
int hit[MAXN];//当前石头额外需要的攻击次数
bool judge(LL x)
{
int res=0, cnt=0;//总攻击次数,当前攻击次数
LL less2=0;//距离衰减
LL less=0;
for(int i=N-1, j=i;i>=0;--i)//i: 当前石头位置,j: 站位
{
while(sqr((LL)(j-i))>=x)//去除掉因为离得太远,无法影响到当前位置的攻击位置
{
less2-=hit[j]*(sqr((LL)(j-i-1)));
less-=hit[j]*(j-i-1);
cnt-=hit[j];
--j;
}
//对于每一对来说,石子每往左移一位,衰减增加2*(j-i)+1
less2+=less*2+cnt;//更新距离衰减
less+=cnt;//更新差值
if(hp[i]<(cnt*x-less2))//当前石头已经被打爆,不需要再站在当前位置攻击
hit[i]=0;
else hit[i]=(hp[i]-cnt*x+less2)/x+1;//得到为了把这个石头打爆,需要在当前位置攻击多少次
cnt+=hit[i];//更新对数
res+=hit[i];
if(res>K)
return false;
}
return res<=K;
}
int main()
{
int T_T;
scanf("%d", &T_T);
while(T_T--)
{
scanf("%d%d", &N, &K);
for(int i=0;i<N;++i)
scanf("%d", &hp[i]);
LL l=0, r=INF;
while(r-l>1)
{
LL mid=(l+r)>>1;
if(judge(mid))
r=mid;
else l=mid;
}
printf("%lld\n", r);
}
return 0;
}