题目

描述

题目大意

给你一堆aia_iai​和bib_ibi​(方便起见用的变量和上面不一样),让你搞出一个xxx(相当于题目中的ba\frac{b}{a}ab​,随便推推就能知道),

使得max⁡ai+bi+aix+bix\max a_i+b_i+a_ix+\frac{b_i}{x}maxai​+bi​+ai​x+xbi​​最小。


思考历程

第一眼看下去,最大最小放一起,显然就是一个二分啊!

然后开始想……想不出来,推了个式子,感觉似乎要三分套三分套三分……

更气的是这题还不好打暴力。

所以推了很久之后什么都没有打。


正解

其实这个题目的正解有好几种。

先说二分的做法(WMY大佬的方法,只可惜被卡了常数):

首先我们二分答案,然后判断是否可行。

要满足ai+bi+aix+bix≤ansa_i+b_i+a_ix+\frac{b_i}{x}\leq ansai​+bi​+ai​x+xbi​​≤ans,

变化一下式子:aix2+(ai+bi−ans)x+bi≤0a_ix^2+(a_i+b_i-ans)x+b_i\leq 0ai​x2+(ai​+bi​−ans)x+bi​≤0

发现可以用一元二次方程的方法来解,

于是对于每个aia_iai​和bib_ibi​,我们都可以得出一个解集。

然后取它们的交集,如果不为空就成立。

正确性显然。

再说三分的做法:

首先有个重要的结论:y=ai+bi+aix+bixy=a_i+b_i+a_ix+\frac{b_i}{x}y=ai​+bi​+ai​x+xbi​​的图像是一个单峰函数(VVV字形,左边陡,右边缓)。

LYL给出了一个很强的证明:

首先ai+bia_i+b_iai​+bi​是定值,先不理它,只考虑y=aix+bixy=a_ix+\frac{b_i}{x}y=ai​x+xbi​​

变化式子:aix2−yx+bi=0a_ix^2-yx+b_i=0ai​x2−yx+bi​=0

一元二次方程!然后算出Δ=y2−4aibi\Delta=y^2-4a_ib_iΔ=y2−4ai​bi​,解为x=y±y2−4aibi2ax=\frac{y \pm\sqrt{y^2-4a_ib_i}}{2a}x=2ay±y2−4ai​bi​​​

这时候就可以脑补出它的图像了……

显然,方程的解只有一个的时候就是顶点,所以顶点为(aba,2ab)(\frac{\sqrt{ab}}{a},2\sqrt{ab})(aab​​,2ab​)

还有YMQ的证明:

将yyy除以aia_iai​,设ci=biaic_i=\frac{b_i}{a_i}ci​=ai​bi​​,则y=x+cixy=x+\frac{c_i}{x}y=x+xci​​

这就相当于反比例函数上的纵坐标和横坐标之和!

显然在直线y=xy=xy=x上最优……(具体证明可以用基本不等式)

整理一下,当x=abax=\frac{\sqrt{ab}}{a}x=aab​​时最优。

证明完了,下面是做法:

对于每个iii,都会有一个图象。将它们放在一起,取maxmaxmax,可以发现图象是单峰(谷)的。

考虑反证,如果图象为WWW形,那么中间交接的那个地方实际上可以继续延伸,在上面更高的地方形成VVV形,所以不可能会出现WWW形。

所以三分出最低点就可以了。

还有一种方法是最优秀的线性方法。

考虑斜率优化。

假设ai&lt;aja_i&lt;a_jai​<aj​且yi&lt;yjy_i&lt;y_jyi​<yj​,那么ai+bi+aix+bix&lt;aj+bj+ajx+bjxa_i+b_i+a_ix+\frac{b_i}{x}&lt;a_j+b_j+a_jx+\frac{b_j}{x}ai​+bi​+ai​x+xbi​​<aj​+bj​+aj​x+xbj​​

变化式子:T(i,j)=−bi−bjai−aj&lt;xT(i,j)=-\frac{b_i-b_j}{a_i-a_j}&lt;xT(i,j)=−ai​−aj​bi​−bj​​<x(TTT只是为了后面方便表示)

然后就可以斜率优化了!

先处理出一个斜率递增的序列,对于序列上的每个点iii,在x∈[T(i−1,i),T(i,i+1)]x\in [T(i-1,i),T(i,i+1)]x∈[T(i−1,i),T(i,i+1)]时,yiy_iyi​是最大的。

所以求出xxx在这个区间内yiy_iyi​的最小值就好了。

将yiy_iyi​的VVV形图象画出来,就可以发现这个区间的位置及对应的最小值的情况。

在顶点左边,跨过顶点,在顶点右边三种情况分类讨论。

这就可以O(1)O(1)O(1)求出它的最小值。

总的来说,这个方法是线性的。


代码

线性做法(我只打了线性的)

using namespace std;
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
inline int input(){
char ch=getchar();
while (ch<'0' || '9'<ch)
ch=getchar();
int x=0;
do{
x=x*10+ch-'0';
ch=getchar();
}
while ('0'<=ch && ch<='9');
return x;
}
#define N 1000010
int n;
struct Monster{
int a,b;
} d[N];
inline bool cmpd(const Monster &x,const Monster &y){
return x.a<y.a || x.a==y.a && x.b>y.b;
}
int q[N],head,tail;
inline bool pd(int i,int j,int k){
return -(long long)(d[i].b-d[j].b)*(d[j].a-d[k].a)>=-(long long)(d[j].b-d[k].b)*(d[i].a-d[j].a);
}
inline double calc(int i,int j){
return -(double)(d[i].b-d[j].b)/(d[i].a-d[j].a);
}
inline double get(int k,double l,double r){
if (l-r>1e-8)
return 1e8;
double mn=sqrt(1ll*d[k].a*d[k].b)/d[k].a;
if (r<mn)
return d[k].a+d[k].b+d[k].a*r+d[k].b/r;
if (l>mn)
return d[k].a+d[k].b+d[k].a*l+d[k].b/l;
return d[k].a+d[k].b+d[k].a*mn+d[k].b/mn;
}
int main(){
n=input();
for (int i=1;i<=n;++i)
d[i]={input(),input()};
sort(d+1,d+n+1,cmpd);
for (int i=1;i<=n;++i){
while (head<tail && pd(q[tail-1],q[tail],i))
tail--;
q[++tail]=i;
}
double ans=get(q[1],1e-4,calc(q[1],q[2]));
for (int i=2;i<tail;++i)
ans=min(ans,get(q[i],calc(q[i-1],q[i]),calc(q[i],q[i+1])));
ans=min(ans,get(q[tail],calc(q[tail-1],q[tail]),1e8));
printf("%.4lf",ans);
return 0;
}

自认为讲解得比较清晰,就不打注释了。


总结

面对这样有关式子和最值的题目,二分和三分都是很好的思考方向。

有时候还可以尝试一下斜率优化。

最后我们认识了这样的函数y=ax+bxy=ax+\frac{b}{x}y=ax+xb​,它的顶点在(aba,2ab)(\frac{\sqrt{ab}}{a},2\sqrt{ab})(aab​​,2ab​)

[JZOJ4640] 【GDOI2017模拟7.15】妖怪的更多相关文章

  1. [JZOJ4633] 【GDOI2017模拟7.15】萌萌哒

    题目 描述 题目大意 给你一个数列,接下来有许多个操作,使得区间[l1,r1][l_1,r_1][l1​,r1​]和[l2,r2][l_2,r_2][l2​,r2​]对应的位置染上同样的颜色(使得它们 ...

  2. 【GDOI2016模拟3.15】基因合成(回文串+性质+DP)

    [GDOI2016模拟3.15]基因合成 题意: 给一个目标串,要求从空串进行最少的操作次数变成目标串,操作有两种: 在串的头或尾加入一个字符. 把串复制一遍后反向接到串的末尾. 因为有回文操作,所以 ...

  3. NOIP2017提高组 模拟赛15(总结)

    NOIP2017提高组 模拟赛15(总结) 第一题 讨厌整除的小明 [题目描述] 小明作为一个数学迷,总会出于数字的一些性质喜欢上某个数字,然而当他喜欢数字k的时候,却十分讨厌那些能够整除k而比k小的 ...

  4. NOIP模拟赛15

    NOIP2017金秋冲刺训练营杯联赛模拟大奖赛第一轮Day1 T1 天天去哪儿吃 直接枚举 #include<cstdio> #include<algorithm> using ...

  5. JZOJ.5281【NOIP2017模拟8.15】钦点

    Description

  6. noip模拟赛#15

    #15 T1:a[i]>=a[i/2].输出a的最大字典序 =>可以发现这是二叉树的情况那么就先预处理出每个点有多少个儿子然后递归处理就可以了. #include<cstdio> ...

  7. [考试反思]0809NOIP模拟测试15:解剖

    说在前面: 不建议阅读.这里没有考试经验,只有一大堆负面情绪. 看了你不会有什么收获.看完了就不要怪我影响了你的心情. 以后不粘排行榜了.没什么意思没什么用. 但是我的意思并不是因为这次没考好的一时兴 ...

  8. [NOIP2018模拟10.15]比赛报告

    闲扯 昨晚又颓到好晚,Yali的降智光环感觉持续至今... 题面好评 T1T3都玩过 逃) T1没看多久就开始写二分+并查集 然后T3看着眼熟想了一个多小时...结果啥都没想出来 赶紧看T2发现还是没 ...

  9. noi.ac NOI挑战营模拟赛1-5

    注:因为博主是个每次考试都爆零垫底的菜鸡,所以此篇博客很有可能咕咕咕 (指只贴AC代码不写题解的......如果我真的不会做的话,就不能怪我了qwqwq) Day1 T1 swap 23pts 从一个 ...

随机推荐

  1. Java-Class-C:org.springframework.http.HttpEntity

    ylbtech-Java-Class-C:org.springframework.http.HttpEntity 1.返回顶部 1.1. import org.springframework.http ...

  2. OAuth2.0的理解-转自阮一峰博客

    一.应用场景 为了理解OAuth的适用场合,让我举一个假设的例子. 有一个"云冲印"的网站,可以将用户储存在Google的照片,冲印出来.用户为了使用该服务,必须让"云冲 ...

  3. Scala 可变长参数

    Scala 允许你指明函数的最后一个参数可以是重复的.这可以允许客户向函数传入可变长度参数列表.想要标注一个重复参数,在参数的类型之后放一个星号. 例如:定义一个可变参数的函数param def pa ...

  4. Spark DataFrame中的join使用说明

    spark sql 中join的类型 Spark DataFrame中join与SQL很像,都有inner join, left join, right join, full join; 类型 说明 ...

  5. 根据单个或多个字段对list对象去重

    pojo  省略 在list 对象中,根据某一字段进行去重,重写Comparator /** * 去重 * * @param orderList * @return * @author ziggo * ...

  6. Python分布式爬虫必学框架scrapy打造搜索引擎✍✍✍

    Python分布式爬虫必学框架scrapy打造搜索引擎  整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身 ...

  7. USACO2012 Haybale stacking /// 区间表示法 oj21556

    题目大意:N个方块 标号1~N  K个操作 操作a b 表示标号a~b区间每位多加一个方块 Input * Line 1: Two space-separated integers, N  K. * ...

  8. 随笔-ansible-2

    通过Ansible来搭建一套Web服务架构.[以AD-HOC的形式] Inventory文件内容如下: [proxy] 192.168.40.254 [app] 192.168.40.243 [nos ...

  9. Windows XP浏览器支持度

    XP最多支持到IE8 谷歌已经结束对Windows XP版Chrome浏览器的支持. 2015年11月,谷歌表示会在2015年结束后,结束对Windows XP版Chrome浏览器的支持.而今,随着2 ...

  10. 《创新者》读书笔记 PB16110698 第五周(~4.5)

    本周我阅读了某同学推荐的<创新者>,这本书实际上是两个世纪以来信息技术的编年史,从巴贝奇的差分机到如今互联网时代的超级计算机,作者通过各个时代里一位位杰出的创新者,将计算机诞生.发展.崛起 ...