我三分这么好吗居然1A啦???提交的时候只是想着先WA一次的。。。。
这题真的很妙啊
首先第一步,就是把僵尸的生命值取一个前缀和,这样造成伤害的时候,可以视为同时对所有僵尸造成伤害。
那么就可以得到一个柿子:
对于第i次进攻,k=max( (sum[i]-sum[j-1]) / x[i]+(i-j)*d ) 其中j表示第j只僵尸。
这样时间的复杂度是O(n^2)的,妥妥的过不去
然后设y1=sum[i],y2=sum[j-1] x1=x[i]+i*d,x2=j*d
柿子就变成了k=(y1-y2)/(x1-x2)这不就是斜率吗
令P(x1,y1),Q(x2,y2)可以发现Q一直是不变的,变的只是P,值得注意的是P的x坐标没有单调性
那么对于Q每次加入用单调栈维护一个下凸包,三分答案出解即可
#include#include #include #include #include #include using namespace std;double sum[110000],w[110000];struct node{ double x,y;}sta[110000];int top;double slope(node n1,node n2){ return (n1.y-n2.y)/(n1.x-n2.x);}int main(){ int n;double d; scanf("%d%lf",&n,&d); double ans=0; sum[0]=0;top=0; for(int i=1;i<=n;i++) { scanf("%lf%lf",&sum[i],&w[i]);sum[i]+=sum[i-1]; node Q; Q.x=double(i)*d,Q.y=sum[i-1]; while(top!=0&&slope(sta[top-1],sta[top])>=slope(sta[top],Q))top--; sta[++top]=Q; node P; P.x=w[i]+double(i)*d,P.y=sum[i]; int l=1,r=top; while(r-l>3) { int mid=(l+r)/2; int mmid=(mid+r)/2; if(slope(P,sta[mid])>slope(P,sta[mmid])) { r=mmid-1; } else l=mid+1; } int ip=l; for(int j=l+1;j<=r;j++) if(slope(P,sta[j])>slope(P,sta[ip]))ip=j; ans+=slope(P,sta[ip]); } printf("%.0lf\n",ans); return 0; }