题意:有 A,B 两种金券,给出 nnn 天内分别的单位价格和可以购买的数量的比例。开始有 SSS 元,求 nnn 天后最多能有多少元。

提示:每次操作一定全买全卖

n≤105n\leq 10^5n≤105

设 fnf_nfn​ 表示第 nnn 天结束后手上最多有多少钱,允许之前某一天卖完后不动留到第 nnn 天。

转移时如果第 nnn 天没卖,就留下 fn−1f_{n-1}fn−1​;否则枚举卖出去的金券是哪天买的。

fi=max⁡{fi−1,max⁡1≤j<i(aixj+biyj)}f_i=\max \{f_{i-1},\max_{1\leq j<i} (a_ix_j+b_iy_j)\}fi​=max{fi−1​,1≤j<imax​(ai​xj​+bi​yj​)}

其中 xj,yjx_j,y_jxj​,yj​ 表示在第 jjj 天两种金券最大能买到的数量,显然能同时取最大值。

xi=rifiriai+bi,yi=firiai+bix_i=\frac{r_if_i}{r_ia_i+b_i},y_i=\frac{f_i}{r_ia_i+b_i}xi​=ri​ai​+bi​ri​fi​​,yi​=ri​ai​+bi​fi​​

考虑一个决策算出的值为 ttt

t=aixj+biyjt=a_ix_j+b_iy_jt=ai​xj​+bi​yj​

yj=−aibixj+tbiy_j=-\frac {a_i}{b_i}x_j+\frac t{b_i}yj​=−bi​ai​​xj​+bi​t​

也就是过 (xj,yj)(x_j,y_j)(xj​,yj​) 斜率为 −aibi-\frac{a_i}{b_i}−bi​ai​​ 的直线中截距最大的

考虑斜率优化,维护一个上凸壳即可

但 xxx 坐标不单调,需要用平衡树/李超线段树/CDQ分治

本文采用 CDQ 分治

核心思想是按 xxx 递增顺序维护左半边的点,用单调栈现求凸壳,右边维护单调递增的询问斜率并查询。

具体而言,因为斜率是输入时就确定的,先在外面把斜率从小到大排序,分治时当前区间是对应的真实标号的区间按斜率排序后的结果。然后

  1. 用类似快排的东西分出左右部分
  2. 分治左半边
  3. 求左半边对右边的贡献,即左半边求凸壳,右边再在凸壳上扫一遍。
  4. 分治右半边
  5. 按 xxx 坐标归并两边的点

复杂度 O(nlog⁡n)O(n\log n)O(nlogn)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <cmath>
#define MAXN 100005
using namespace std;
const double eps=1e-9,inf=1e9;
double f[MAXN];
struct node{double x,y,k,a,b,r;int id;}p[MAXN],t1[MAXN],t2[MAXN];
inline bool cmp(const node& x,const node& y){return x.k<y.k;}
inline double slope(const node& a,const node& b)
{if (fabs(a.x-b.x)<eps) return inf;return (a.y-b.y)/(a.x-b.x);
}
void solve(int l,int r)
{if (l==r){f[l]=max(f[l],f[l-1]);p[l].y=f[l]/(p[l].r*p[l].a+p[l].b);p[l].x=p[l].y*p[l].r;return;}int mid=(l+r)>>1;int cnt1=0,cnt2=0;for (int i=l;i<=r;i++)if (p[i].id<=mid) t1[++cnt1]=p[i];else t2[++cnt2]=p[i];for (int i=1;i<=cnt1;i++) p[l+i-1]=t1[i];for (int i=1;i<=cnt2;i++) p[mid+i]=t2[i];solve(l,mid);int tp=0;for (int i=l;i<=mid;i++) {while (tp>1&&slope(t1[tp-1],t1[tp])+eps<slope(t1[tp],p[i])) --tp;t1[++tp]=p[i]; } for (int i=mid+1;i<=r;i++){while (tp>1&&slope(t1[tp-1],t1[tp])<=p[i].k+eps) --tp;f[p[i].id]=max(f[p[i].id],p[i].a*t1[tp].x+p[i].b*t1[tp].y);}solve(mid+1,r);cnt1=l,cnt2=mid+1,tp=l;while (cnt1<=mid||cnt2<=r)if (cnt1<=mid&&(cnt2>r||p[cnt1].x<p[cnt2].x+eps)) t1[tp++]=p[cnt1++];else t1[tp++]=p[cnt2++];for (int i=l;i<=r;i++) p[i]=t1[i];
}
int main()
{int n;scanf("%d%lf",&n,&f[0]);for (int i=1;i<=n;i++) scanf("%lf%lf%lf",&p[i].a,&p[i].b,&p[i].r),p[i].k=-p[i].a/p[i].b,p[i].id=i;sort(p+1,p+n+1,cmp);solve(1,n);printf("%.3f",f[n]);return 0;
}

【NOI2007】货币兑换【任意坐标斜率优化】【CDQ分治】相关推荐

  1. 【BZOJ1492】[NOI2007]货币兑换Cash 斜率优化+cdq分治

    [BZOJ10492][NOI2007]货币兑换Cash Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下简称B券).每 ...

  2. 【牛客NOIP模拟】 牛牛的RPG游戏【二维偏序】【任意坐标斜率优化】【CDQ 分治】【李超线段树】

    题意: n×mn\times mn×m 的网格图,每个点有两个权值 vali,j,bufi,jval_{i,j},buf_{i,j}vali,j​,bufi,j​,从 (1,1)(1,1)(1,1) ...

  3. bzoj 2149 拆迁队 斜率优化+cdq分治

    题面 题目传送门 解法 从来没写过这样的-- 第一问非常简单,能够从 j j j转移到 i i i的条件显然为 a [ i ] − a [ j ] ≥ i − j a[i]-a[j]≥i-j a[i] ...

  4. 【CEOI2017】Building Bridges【任意坐标斜率优化】【李超线段树】

    题意:有 nnn 个柱子,每个柱子有高度 hih_ihi​.你需要在柱子间修桥,在 i,ji,ji,j 间修桥代价为 (hi−hj)2(h_i-h_j)^2(hi​−hj​)2,桥梁只能在柱子处相交, ...

  5. 斜率优化(CDQ分治,Splay平衡树):BZOJ 1492: [NOI2007]货币兑换Cash

    Description Input 第一行两个正整数N.S,分别表示小Y 能预知的天数以及初始时拥有的钱数. 接下来N 行,第K 行三个实数AK.BK.RateK,意义如题目中所述 Output 只有 ...

  6. bzoj1492 [NOI2007]货币兑换Cash (斜率DP+cdq分治)

    题意:到处都找得到. 我没看错的话当年考试的时候的题面里头,是提示了买卖一定是全部买入和卖出的.这样一来就好办了.cdq的论文里面那个F并不是她所说的那样,而是就是那个最优值.方程转移的时候实际上是枚 ...

  7. bzoj1492 货币兑换cash dp斜率优化+splay/cdq分治

    斜率优化 首先,由于如果在i天买在j天卖有利可图,那么最优方法就是在i天花完钱在j天卖完.我们令 f i f_i fi​为第i天可以得到的最多钱数,然后可以先列方程求出花完钱在第j天得到的两种金券数 ...

  8. [BZOJ1492] [NOI2007]货币兑换Cash 斜率优化+cdq/平衡树维护凸包

    1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 5907  Solved: 2377 [Submit][S ...

  9. YbtOJ#493-最大分数【斜率优化dp,分治】

    正题 题目链接:http://172.17.55.160/contest/117/problem/1 题目大意 nnn个数的一个序列,给其中的一些数打上标记. 一个标记方案的贡献为s1s_1s1​表示 ...

最新文章

  1. Python使用matplotlib可视化多分类变量组合下分组小提琴图、使用seaborn中的catplot函数可视化多分类变量组合下分组小提琴图(Categorical Plots)
  2. Java中的运行期类型鉴定
  3. java实现封装的三步是_JAVA基础-封装
  4. PHP 继承新增,php类的扩展和继承用法实例
  5. Linux inode 详解
  6. Centos系列 Curl error (37): Couldn‘t read a file:// file for file:///etc/pki/rpm-gpg/RPM-GPG-KEY-XXXX
  7. NanoPC-T3 64位裸机编程 —— 启动和运行状态切换
  8. 官网的python下载安装后无需配置即可使用_图文解说少儿编程软件python下载安装,没有经验的新手也可以做到...
  9. 机器学习基础(四十六)—— 遗传算法(GA)
  10. GTK 4.0 图形工具包正式发布
  11. http 回应头的闷事
  12. Win10 SecoClient连接报错:无法启用虚拟网卡适配
  13. 微信小程序使用code码获取用户信息提示errcode:40163 code been used,rid:
  14. 计算机考研数据库原理知识,数据库原理考研资料题库真题整理
  15. WUSTOJ 1275: 男神的逆袭(Java)
  16. 五、python 缺失值处理(Imputation)
  17. Horizon Culling 地平线踢出法
  18. sflow-rt 3.0 安装
  19. DateCalander
  20. 精彩英语写作200句对译

热门文章

  1. 中国十大最美梯田,个个都美如画!
  2. 从时速100公里行驶的车上向后发射时速100公里的棒球,会发生什么?
  3. adb android源码分析,Android源码分析(十六)----adb shell 命令进行OTA升级
  4. 多个php一个机器,如何利用docker在同一台机器上搭建多套php开发环境?
  5. mysql 1054 42s22_MySQL ERROR 1054(42S22)
  6. 用python写简单爬虫,用Python写简单的爬虫
  7. java中JOptionPane类_java:JOptionPane类消息框总结
  8. python input函数无法输入字符串_Python手把手教程之用户输入input函数
  9. 西北纺织工学院97级计算机系学生毕业名单,原西北纺织工学院更名为西安工程大学...
  10. oracle天数加个随机数,如何给一个表某列加上指定的随机数