题目

描述

题目大意

给你一堆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​)

转载于:https://www.cnblogs.com/jz-597/p/11145220.html

[JZOJ4640] 【GDOI2017模拟7.15】妖怪相关推荐

  1. jzoj4640. 【GDOI2017模拟7.15】妖怪

    Description Input Output Sample Input 3 1 1 1 2 2 2 Sample Output 8.0000 Data Constraint 题解 我还挺喜欢数学的 ...

  2. 【折半搜索-经典题目】中山纪念中学暑期游Day13——【GDOI2017模拟8.15】Buy

    前言 考试时有道题目用到了[折半搜索] 老师推荐了这道经典题目让大家练习[前后部分算法不同]的题目 虽然不知道我有没有时间做,好歹先把题目记录一下,免得以后找不到了qwq 题目 Input Outpu ...

  3. [双指针|模拟] leetcode 15 三数之和

    [双指针|模拟] leetcode 15 三数之和 1.题目 题目链接 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ? ...

  4. jzoj 5906. 【NOIP2018模拟10.15】传送门(树形dp)

    5906. [NOIP2018模拟10.15]传送门 Description 8102年,Normalgod在GLaDOS的帮助下,研制出了传送枪.但GLaDOS想把传送枪据为己有,于是把Normal ...

  5. 2020.03.11模拟赛15(第一题)

    1.水果盛宴(fruit) 题目描述 贝茜又再一次地闯入了 Farmer John 的房子!她在厨房发现了一堆柠檬和一堆橘子(每堆都有无限多个),并且,她希望尽可能地多吃. 贝茜的有一个饱腹值上限 T ...

  6. jzoj5904. 【NOIP2018模拟10.15】刺客信条(并查集)

    5904. [NOIP2018模拟10.15]刺客信条 Description 故事发生在1486 年的意大利,Ezio 原本只是一个文艺复兴时期的贵族,后来因为家族成员受到圣殿骑士的杀害,决心成为一 ...

  7. JZOJ 5977. 【清华2019冬令营模拟12.15】堆

    Description Input Output Sample Input 10 10 0 1 1 2 2 4 3 12 2 6 2 15 3 5 3 10 7 7 9 16 2 3 1 10 9 2 ...

  8. JZOJ 3775. 【NOIP2014模拟8.15】因子的排列

    Description 一天,小B学习了分解质因数的相关内容.他发现,一个数的质因子可以有许多不同的排列方式,例如20=2*2*5=2*5*2=5*2*2,那么小B认为20的质因子有3种不同的排列方式 ...

  9. NOIP模拟测试15「建造城市city(插板法)·轰炸·石头剪刀布」

    建造城市 题解 先思考一个简单问题 10个$toot$ 放进5间房屋,每个房屋至少有1个$toot$,方案数 思考:插板法,$10$个$toot$有$9$个缝隙,$5$间房屋转化为$4$个挡板,放在t ...

  10. jzoj3771. 【NOI2015模拟8.15】小 Z 的烦恼

    Description 小 Z 最近遇上了大麻烦,他的数学分析挂科了.于是他只好找数分老师求情. 善良的数分老师答应不挂他,但是要求小 Z 帮助他一起解决一个难题问题是这样的,现在有 n 个标号为 1 ...

最新文章

  1. oracle列字符可以增加长度,ORACLE字符列长度语义
  2. Serverless Kubernetes 容器服务介绍
  3. Python中有几种办法交换两个变量的值?
  4. 四、爬虫中的urllib库使用
  5. 多路 IO 转接 :epoll 函数
  6. mysql 协议的query包及解析
  7. mysql blob key length_mysql提示used in key specification without a key length
  8. 尽可能地做到无服务器,但不止于此
  9. oracle唯一索引能删除吗,Oracle:ora-02429:无法用于删除强制唯一/主键的索引 解决...
  10. 计算机专业英语课后答案北京理工大学,计算机专业英语
  11. Google docs支持上传任何文档包括pdf...Cool!
  12. 惠普打印机故障代码_惠普激光打印机故障代码
  13. Linux i2c-tools使用及调试
  14. 两种方法求x的n次幂
  15. matlab corner 舍弃,成长就是不断地丢弃与拾取 — 读The Glass Castle《玻璃城堡》有感...
  16. redis之集群运维总结
  17. Unreal Engine 4 渲染目标(Render Target)教程 之 实现雪地足迹(下)
  18. C++ 之 for 循环 | C++11 for 循环 | 内存 Destory 示例
  19. shell脚本 sh shebang “#!/bin/sh“
  20. dblink(dblink是什么意思)

热门文章

  1. Bagging与Boosting的区别与联系
  2. Linux怎么登录redis数据库,Linux 系统上 Redis 数据库的 安装 部署 使用
  3. 微信小程序云开发教程-云函数入门(2)-接收参数、前端调用
  4. 记飞机大战小游戏1.0
  5. linux赋权限2770,Linux权限:SUID,SGID以及粘滞位
  6. linux之VMware安装Centos7
  7. 二十五、JAVA多线程(二、吃苹果案例)
  8. spring简易学习笔记三(AOP)
  9. Win 10 下载与安装 Oracle 12c 详细图解 与 Oracle 12c 卸载
  10. Linux 网络命令 ip、ifconfig