[BZOJ3203] [SDOI2013]保护出题人(二分+凸包)

题面

题面较长,略

分析

对于第i关,我们算出能够打死前k个个僵尸的最小能力值,再取最大值就可以得到\(y_i\).

前j-1个僵尸到门的距离为\(x_i+(i-j+1) \times d\),血量为\(sum[i]-sum[j]\),因此

\[y_i=max(\frac{sum_i-sum_j}{x_i+(i-j+1) \times d})= max(\frac{sum_i-sum_j}{x_i+i \times d-(j+1)\times d})
\]

这个方程没法用一般的斜率优化来转移,但我们注意到除法很像斜率的形式,实际上是\((x_i+i \times d,sum_i)\)和\(((j+1)\times d,sum_j)\)之间的斜率

那么问题就转化成,给出一个定点\((x_i+i \times d,sum_i)\),求一个点\(((j+1)\times d,sum_j)\),使得这两点间斜率最大

显然备选的点应该在一个斜率单调递增凸壳上。那么我们可以像斜率优化那样维护一个凸壳。找斜率最大点显然可以三分,但还有更简单的方法。注意到斜率最大点下方的点到定点的向量,和凸壳上相邻点的向量的叉积为负。我们只要找到x坐标最小,且叉积为正的点即可,直接二分答案。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100000
#define eps 1e-6
using namespace std;
int n;
double d;
struct Vector{
double x;
double y;
Vector(){ }
Vector(double _x,double _y){
x=_x;
y=_y;
}
friend Vector operator + (Vector p,Vector q){
return Vector(p.x+q.x,p.y+q.y);
}
friend Vector operator - (Vector p,Vector q){
return Vector(p.x-q.x,p.y-q.y);
}
};
typedef Vector point;
double cross(Vector p,Vector q){
return p.x*q.y-p.y*q.x;
}
double slope(point p,point q){
return (p.y-q.y)/(p.x-q.x);
} double a[maxn+5],x[maxn+5];
double suma[maxn+5];
point s[maxn+5]; int bin_search(int l,int r,point k){
int ans=1;
int mid;
while(l<=r){
mid=(l+r)>>1;
if(cross(s[mid+1]-s[mid],k-s[mid])<=eps){
ans=mid;
r=mid-1;
}else l=mid+1;
}
return ans;
}
int main(){
scanf("%d %lf",&n,&d);
for(int i=1;i<=n;i++){
scanf("%lf %lf",&a[i],&x[i]);
suma[i]=suma[i-1]+a[i];
}
int top=0;
double ans=0;
s[++top]=point(d,0); //((0+1)*d,suma[0])
for(int i=1;i<=n;i++){
int best=bin_search(1,top,point(x[i]+i*d,suma[i]));//找到斜率最大的点
double val=slope(point(x[i]+i*d,suma[i]),s[best]);
ans+=val;
point newp=point((i+1)*d,suma[i]);//插入新的可行点
while(top>1&&cross(s[top]-s[top-1],newp-s[top-1])<=eps) top--;
s[++top]=newp;
}
printf("%.0f\n",ans);
}

[BZOJ3203] [SDOI2013]保护出题人(二分+凸包)的更多相关文章

  1. 【BZOJ3203】[Sdoi2013]保护出题人 二分+凸包

    [BZOJ3203][Sdoi2013]保护出题人 Description Input 第一行两个空格隔开的正整数n和d,分别表示关数和相邻僵尸间的距离.接下来n行每行两个空格隔开的正整数,第i + ...

  2. [BZOJ3203][SDOI2013]保护出题人(凸包+三分)

    https://www.cnblogs.com/Skyminer/p/6435544.html 先不要急于转化成几何模型,先把式子化到底再对应到几何图形中去. #include<cstdio&g ...

  3. [bzoj3203][Sdoi2013]保护出题人

    人生第一道三分?... 把进攻序列里的前i只僵尸看成一个点,横坐标是第i只僵尸到达的时间,纵坐标是这i只僵尸的血量总和..就是说植物必须在这段时间内输出这些伤害..那么单位时间的输出伤害就是斜率了. ...

  4. BZOJ3203 SDOI2013保护出题人(三分)

    给a做一个前缀和,那么现在每次所查询的就是(sn-sk)/(bn+nd-(k+1)d)的最大值.这个式子可以看成是(bn+nd,sn)和((k+1)d,sk)所成直线的斜率. 脑补一条直线不断减小斜率 ...

  5. 【洛谷 P3299】 [SDOI2013]保护出题人 (凸包,三分,斜率优化)

    题目链接 易得第\(i\)关的最小攻击力为\(\max_{j=1}^i\frac{sum[i]-sum[j-1]}{x+d*(i-j)}\) 十分像一个斜率式,于是看作一个点\(P(x+d*i,sum ...

  6. 洛谷 P3299 [SDOI2013]保护出题人 解题报告

    P3299 [SDOI2013]保护出题人 题目描述 出题人铭铭认为给SDOI2012出题太可怕了,因为总要被骂,于是他又给SDOI2013出题了. 参加SDOI2012的小朋友们释放出大量的僵尸,企 ...

  7. 【BZOJ3203】保护出题人(动态规划,斜率优化)

    [BZOJ3203]保护出题人(动态规划,斜率优化) 题面 BZOJ 洛谷 题解 在最优情况下,肯定是存在某只僵尸在到达重点的那一瞬间将其打死 我们现在知道了每只僵尸到达终点的时间,因为僵尸要依次打死 ...

  8. [SDOI2013]保护出题人

    题目 出题人铭铭认为给SDOI2012出题太可怕了,因为总要被骂,于是他又给SDOI2013出题了. 参加SDOI2012的小朋友们释放出大量的僵尸,企图攻击铭铭的家.而你作为SDOI2013的参赛者 ...

  9. 【bzoj3203】[Sdoi2013]保护出题人 凸包+二分

    题目描述 输入 第一行两个空格隔开的正整数n和d,分别表示关数和相邻僵尸间的距离.接下来n行每行两个空格隔开的正整数,第i + 1行为Ai和 Xi,分别表示相比上一关在僵尸队列排头增加血量为Ai 点的 ...

随机推荐

  1. POJ 3741 Raid (平面最近点对)

    $ POJ~3741~Raid $ (平面最近点对) $ solution: $ 有两种点,现在求最近的平面点对.这是一道分治板子,但是当时还是想了很久,明明知道有最近平面点对,但还是觉得有点不对劲. ...

  2. hadoop中yarn

    一.yarn的概述 Apache Yarn(Yet Another Resource Negotiator的缩写)是hadoop集群资源管理器系统,Yarn从hadoop 2引入,最初是为了改善Map ...

  3. man clock

    CLOCK(3)   Linux程序员手册   CLOCK(3) 名称  时钟-确定处理器时间 简介  #include <time.h>    clock_t clock(void);  ...

  4. Centos 6.4 x86_64 最小化安装后的优化——还需要整理

      Centos 6.4 x86_64 最小化安装后的优化   购买了服务器以后要做的第一件事就是安装操作系统了,这里推荐安装 Centos 6.4 x86_64,安装系统时要选择最小化安装(不需要图 ...

  5. nyoj 952 : 最大四边形 (计算几何)

    题目链接 任意四边形均可看作是两个三角形拼接得到的(即使是凹四边形),故 可以O(n^2)枚举所有的线段,然后对每条线段O(n)枚举线段端点外的其他点,用来更新以此线段构成的三角形的有向面积的最大值m ...

  6. 51nod1820 长城之旅

    题目描述 BB 痛失一血(打了场Comet OJ回来就没了) 不过后来又刷了一道水题 题解 LCM+取模=结论题 结论1 \(gcd(k^{2^i}+1,k^{2^j}+1)=1 (i\neq j 且 ...

  7. ubuntu16.04 下 C# mono开发环境搭建

    本文转自:https://www.cnblogs.com/2186009311CFF/p/9204031.html 前记 之前我一直不看好C#的前景,因为我认为它只能在windows下运行,不兼容,对 ...

  8. Day_04-数组,元组,列表

    # for i in range(5): # for j in range(5): # print(i,j) # import re # def rm(): # a = ' 1 2 3 4 5 ' # ...

  9. PHP高手干货分享:不能不看的50个细节!【PHP培训教程】

    兄弟连分享PHP高手干货:不能不看的50个细节 1.用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会,注意:只有echo能这么做,它是一种可以 ...

  10. 【WINDOWS】设置路由表实现有线内网,无线外网

    前提!!! 需要有线无线双网卡