1. 程式人生 > >bzoj3203: [Sdoi2013]保護出題人

bzoj3203: [Sdoi2013]保護出題人

AI name tdi struct class d+ namespace 2.x OS

我三分這麽好嗎居然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<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
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; }

bzoj3203: [Sdoi2013]保護出題人