【SDOI2013】【BZOJ3203】保护出题人

Description

Input

第一行两个空格隔开的正整数n和d,分别表示关数和相邻僵尸间的距离。接下来n行每行两个空格隔开的正整数,第i + 1行为Ai和 Xi,分别表示相比上一关在僵尸队列排头增加血量为Ai 点的僵尸,排头僵尸从距离房子Xi米处开始接近。

Output

一个数,n关植物攻击力的最小总和 ,保留到整数。

Sample Input

5 2

3 3

1 1

10 8

4 8

2 3

Sample Output

7
HINT

第一关:距离房子3米处有一只血量3点的僵尸,植物最小攻击力为1.00000; 第二关:距离房子1米处有一只血量1点的僵尸、3米处有血量3点的僵尸,植物最小攻击力为1.33333; 第三关:距离房子8米处有一只血量10点的僵尸、10米处有血量1点的僵尸、12米处有血量3点的僵尸,植物最小攻击力为1.25000; 第四关:距离房子8米处有一只血量4点的僵尸、10米处有血量10点的僵尸、12米处有血量1点的僵尸、14米处有血量3点的僵尸,植物最小攻击力为1.40000; 第五关:距离房子3米处有一只血量2点的僵尸、5米处有血量4点的僵尸、7米处有 血量10点的僵尸、9米处有血量1点的僵尸、11米处有血量3点的僵尸,植物最小攻击力 为2.28571。 植物攻击力的最小总和为7.26905。

对于100%的数据, 1≤n≤10^5,1≤d≤10^12,1≤x≤ 10^12,1≤a≤10^12

Source

感人至深…最后我竟然没发现答案是在凸包上所以可以三分T_T
hta的题解

#include
#include
#include
#include
#include
#define MAXN 100010
#define eps 1e-20
using namespace std;
int n,top;
double d,ans;
double a[MAXN],x[MAXN];
struct Point
{
    double x,y;
    friend Point operator +(Point a,Point b)    {return (Point){a.x+b.x,a.y+b.y};}
    friend Point operator -(Point a,Point b)    {return (Point){a.x-b.x,a.y-b.y};}
    friend double operator *(Point a,Point b)   {return a.x*b.y-a.y*b.x;}
}sta[MAXN];
double slope(Point a,Point b)   {return (a.y-b.y)/(a.x-b.x);}
int main()
{
    scanf("%d%lf",&n,&d);double sum=0,maxn=0;
    for (int i=1;i<=n;i++)  scanf("%lf%lf",&a[i],&x[i]);
    for (int i=1;i<=n;i++)
    {
        maxn=0;Point now=(Point){i*d,sum};sum+=a[i];
        while (top>1&&(now-sta[top-1])*(sta[top]-sta[top-1])>=-eps) top--;
        sta[++top]=now;now=(Point){x[i]+i*d,sum};
        int l=1,r=top,mid1,mid2,len;
        while (r-l>=3)
        {
            len=(r-l+1)/3;mid1=l+len;mid2=r-len;
            if (slope(sta[mid1],now)else    r=mid2;
        }
        for (int j=l;j<=r;j++)  maxn=max(maxn,slope(sta[j],now));ans+=maxn;
    }
    printf("%.0f\n",ans);
}

你可能感兴趣的:(随便搞搞)