bzoj3203: [Sdoi2013]保护出题人

我三分这么好吗居然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
",ans);
    return 0; 
} 
原文地址:https://www.cnblogs.com/AKCqhzdy/p/8909010.html