题目
题解
数据确实水,n2 算法能过1e4就算了,1e5都能过一组,服了
研究题目与样例数据,我们得知一个重要信息,僵尸死了之后,多余的伤害会传到后面去。打死最前面的僵尸才能打后面,僵尸每秒都移动,那么对于第i个僵尸,我们可以将前面的僵尸与i本身绑在一起(生命值之和),求此时需要多少攻击力,即生命值之和除以i离红线的距离
那么我们轻松可以得到f[i] = max(sum[i] - sum[j - 1]) / (d * (i - j) + x[i])。
f[i]表示第i关需要最小攻击力
最后加起来便是答案
先给一个朴素的代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<ctime>
using namespace std;
int n;
long long sum[100005],a[100005],x[100005],d;
double ans;
long long read(){
long long x = 0,f = 1;
char s = getchar();
while (s < '0' || s > '9'){
if (s == '-')
f = -1;
s = getchar();
}
while (s >= '0' && s <= '9'){
x = x * 10 + s - '0';
s = getchar();
}
return f * x;
}
int main(){
scanf ("%d%lld",&n,&d);
for (int i = 1;i <= n;i ++)
a[i] = read(),x[i] = read();
for (int i = 1;i <= n;i ++){
for (int j = i;j >= 2;j --)
sum[j] = sum[j - 1] + a[i];
sum[1] = a[i];
double maxn = 0;
for (int j = 1;j <= i;j ++)
maxn = max(maxn,1.0 * sum[j] / (d * (j - 1) + x[i]));
ans += maxn;
}
printf("%.0lf
",ans);
}
但这个过不了,我们再观察式子,发现是这(x[i]+d*i,sum[i]),(d * j,sum[j - 1])两点的斜率。所以维护一个下凸包,二分求最大斜率即可
我太垃圾了,放一个巨佬博客
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<ctime>
using namespace std;
struct node{
long long x,y;
node(){};
node(long long X,long long Y){
x = X,y = Y;
}
}Q[100005];
int n,cnt;
long long sum[100005],a[100005],x[100005],d;
double ans;
double get(node a,node b){
return 1.0*(a.y - b.y) / (a.x - b.x);
}
int main(){
scanf ("%d%lld",&n,&d);
for (int i = 1;i <= n;i ++)
scanf ("%lld%lld",&a[i],&x[i]);
for (int i = 1;i <= n;i ++)
sum[i] = sum[i - 1] + a[i];
Q[0] = node(0,0);
for (int i = 1;i <= n;i ++){
node tmp = node(i * d,sum[i - 1]);
while (cnt && get(Q[cnt - 1],Q[cnt]) > get(Q[cnt],tmp))
cnt --;
Q[++ cnt] = tmp;
tmp = node(i * d + x[i],sum[i]);
int l = 1,r = cnt,pos = 0;
while (l <= r){
int mid = (l + r) / 2;
if (get(Q[mid],tmp) > get(Q[mid - 1],tmp)){
pos = mid;
l = mid + 1;
}
else
r = mid - 1;
}
ans += get(Q[pos],tmp);
}
printf("%.0lf
",ans);
}