bzoj 1492: [NOI2007]货币兑换Cash
Description


Input
Output
只有一个实数MaxProfit,表示第N天的操作结束时能够获得的最大的金钱数目。答案保留3位小数。
Sample Input
1 1 1
1 2 2
2 2 3
Sample Output
HINT
Source
这其实是一道大火题,是CDQ分治的发明题 Orz,Orz,Orz
蒟蒻如我连一个单调都做不出,而这个题就真的实在玩蛇皮了
题目提示解题法:
numa=numb*rk;
numb*(rk*ak+bk)=f[k];
numb=f[k]/(rk*ak+bk);
// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<queue>
#include<set>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#define lson num<<1
#define rson num<<1|1
using namespace std;
typedef long long ll;
const int N=100050;
double f[N],a[N],b[N],ak[N],bk[N],rk[N],S;
int n;
int main(){
scanf("%d",&n);scanf("%lf",&S);
for(int i=1;i<=n;i++){
scanf("%lf%lf%lf",&ak[i],&bk[i],&rk[i]);
}
f[0]=S;
for(int i=1;i<=n;i++){
f[i]=f[i-1];
for(int j=1;j<i;j++){
b[j]=f[j]/(rk[j]*ak[j]+bk[j]);a[j]=b[j]*rk[j];
f[i]=max(f[i],a[j]*ak[i]+b[j]*bk[i]);
}
}
printf("%.3f",f[n]);
}
这是我用线打斜率优化的第一道题,关于线的斜率优化表示法见我的斜率优化总结
这一题的方程:
a[j]*ak[i]+b[j]*bk[i]
同时提出一个ak[i]变为:
(a[j]+b[j]*(bk[i]/ak[i]))*ak[i];运用线的套路
令b=a[j],b[j]=k,x=(bk[i]/ak[i]),ak为乘在外面的一个常数
我们发现斜率不是单调的,横坐标也不是单调的,这就不同于普通的都满足单调性的斜率优化
我们考虑普通的斜率优化
需要依赖于斜率的单调性来用单调队列进行队尾的更新来实现O(n)的维护半平面交
需要依赖于横坐标的单调性来用单调队列进行队头决策的移动来实现O(n)的决策转移
然而我们发现这两个步骤都需要依赖于有序,所以CDQ就可以通过离线化无序为有序
我们考虑到转移相当于是一个偏序问题,首先必须满足序号小的向序号大的转移
考虑到CDQ分治的基本思路,用左边的答案来更新右边的答案
我们可以相当于把问题转化为左右两个部分的偏序问题
我们要用左边来更新右边,我们相当于需要在左边斜率递增(斜率单调这个用归并即可以实现)才可以用单调队列实现O(n)维护一个决策的半平面交
然后我们需要在右边横坐标递增,利用左边的决策的半平面交再利用单调队列实现O(n)的决策转移(横坐标单调这个在外面sort一遍即可)
这样相当于两边都是一个二维的偏序问题,至此问题已经被完美解决了,整个分治的流程十分完美
时间复杂度:nlogn
代码:
// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<queue>
#include<set>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#define lson num<<1
#define rson num<<1|1
#define eps 1e-9
using namespace std;
typedef long long ll;
const int N=100050;
int cnt;
struct data{double k,x,b;int id;}g[N],p[N],q[N];
double f[N],ak[N],bk[N],rk[N];
bool cmp(const data &a,const data &b){
return a.x<b.x;
}
void solve(int l,int r){
if(l==r) return;
int mid=(l+r)>>1,l1=l,l2=mid+1,head=1,tail=0;
double MAX=0;
for(int i=l;i<=r;i++){
cnt++;
if(g[i].id<=mid) p[l1++]=g[i];
else p[l2++]=g[i];
}
for(int i=l;i<=r;i++) g[i]=p[i];
solve(l,mid);
for(int i=l;i<=mid;i++){
while(head<tail&&(g[i].k-q[tail].k)*(q[tail-1].b-q[tail].b)>=(q[tail].k-q[tail-1].k)*(q[tail].b-g[i].b))
tail--;
q[++tail]=g[i],MAX=max(MAX,f[g[i].id]);
}
sort(g+mid+1,g+r+1,cmp);
for(int i=mid+1;i<=r;i++){
while(head<tail&&q[head].k*g[i].x+q[head].b<=q[head+1].k*g[i].x+q[head+1].b)
head++;
f[g[i].id]=max(f[g[i].id],max(MAX,ak[g[i].id]*(q[head].k*g[i].x+q[head].b)));
g[i].k=f[g[i].id]/(ak[g[i].id]*rk[g[i].id]+bk[g[i].id]),g[i].b=g[i].k*rk[g[i].id];
}
solve(mid+1,r);l1=l,l2=mid+1;
for(int i=l;i<=r;i++){
if(l2>r||(l1<=mid&&g[l1].k<=g[l2].k)) p[i]=g[l1++];
else p[i]=g[l2++];
}
for(int i=l;i<=r;i++) g[i]=p[i];
}
int main()
{
int n;
cin>>n;scanf("%lf",&f[0]);
for(int i=1;i<=n;i++){
scanf("%lf%lf%lf",&ak[i],&bk[i],&rk[i]);
f[i]=f[0];
g[i].id=i,g[i].x=bk[i]/ak[i],g[i].k=f[i]/(rk[i]*ak[i]+bk[i]),g[i].b=g[i].k*rk[i];
}
solve(1,n);
printf("%.3f",f[n]);
}
bzoj 1492: [NOI2007]货币兑换Cash的更多相关文章
- BZOJ 1492: [NOI2007]货币兑换Cash( dp + 平衡树 )
dp(i) = max(dp(i-1), x[j]*a[i]+y[j]*b[i]), 0<j<i. x, y表示某天拥有的最多钱去买金券, 金券a和金券b的数量. 然后就很明显了...平衡 ...
- ●BZOJ 1492 [NOI2007]货币兑换Cash
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1492 题解: 斜率优化DP,CDQ分治 定义$DP[i]$为第i天结束后的最大收益. 由于题 ...
- bzoj 1492 [NOI2007]货币兑换Cash(斜率dp+cdq分治)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1492 [题意] 有AB两种货币,每天可以可以付IPi元,买到A券和B券,且A:B= ...
- 斜率优化(CDQ分治,Splay平衡树):BZOJ 1492: [NOI2007]货币兑换Cash
Description Input 第一行两个正整数N.S,分别表示小Y 能预知的天数以及初始时拥有的钱数. 接下来N 行,第K 行三个实数AK.BK.RateK,意义如题目中所述 Output 只有 ...
- BZOJ 1492: [NOI2007]货币兑换Cash [CDQ分治 斜率优化DP]
传送门 题意:不想写... 扔链接就跑 好吧我回来了 首先发现每次兑换一定是全部兑换,因为你兑换说明有利可图,是为了后面的某一天两种卷的汇率差别明显而兑换 那么一定拿全利啊,一定比多天的组合好 $f[ ...
- BZOJ 1492 [NOI2007]货币兑换Cash:斜率优化dp + cdq分治
传送门 题意 初始时你有 $ s $ 元,接下来有 $ n $ 天. 在第 $ i $ 天,A券的价值为 $ A[i] $ ,B券的价值为 $ B[i] $ . 在第 $ i $ 天,你可以进行两种操 ...
- bzoj 1492: [NOI2007]货币兑换Cash【贪心+斜率优化dp+cdq】
参考:http://www.cnblogs.com/lidaxin/p/5240220.html 虽然splay会方便很多,但是懒得写,于是写了cdq 首先要想到贪心的思路,因为如果在某天买入是能得到 ...
- BZOJ 1492 [NOI2007]货币兑换Cash (CDQ分治/splay 维护凸包)
题目大意:太长了略 splay调了两天一直WA弃疗了 首先,我们可以猜一个贪心,如果买/卖,就一定都买/卖掉,否则不买/卖 反正货币的行情都是已知的,没有任何风险,所以肯定要选择最最最优的方案了 容易 ...
- BZOJ 1492: [NOI2007]货币兑换Cash 斜率优化 + splay动态维护凸包
Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下 简称B券).每个持有金券的顾客都有一个自己的帐户.金券的数目可以是一个 ...
随机推荐
- npm模块管理器入门
什么是 NPM npm 是 Node 官方提供的包管理工具,他已经成了 Node 包的标准发布平台,用于 Node 包的发布.传播.依赖控制.npm 提供了命令行工具,使你可以方便地下载.安装.升级. ...
- Python带参数的装饰器
在装饰器函数里传入参数 # -*- coding: utf-8 -*- # 2017/12/2 21:38 # 这不是什么黑魔法,你只需要让包装器传递参数: def a_decorator_passi ...
- 【jQuery插件】使用cropper实现简单的头像裁剪并上传
插件介绍 这是一个我在写以前的项目的途中发现的一个国人写的jQuery图像裁剪插件,当时想实现用户资料的头像上传功能,并且能够预览图片,和对图片进行简单的裁剪.旋转,花了不少时间才看到了这个插件,感觉 ...
- spring框架的一些技术总结
纵观现在互联网行业,java的地位依然不可动摇,因为java拥有着的众多开发人员和适用性广,技术与解决技术大部分开源等特点,因此java依然是众多众多开发行业作为互联网开发的首选,而说到开发,我们就不 ...
- Retrofit网络请求库应用01
PS:什么是Retrofit? 在官方文档中有这样一句话--A type-safe HTTP client for Android and Java(一个类型安全的http client库),具体的话 ...
- HAUT 1261地狱飞龙 自适应辛普森 数值积分
1261: 地狱飞龙 时间限制: 1 秒 内存限制: 64 MB 提交: 300 解决: 68 题目描述 最近clover迷上了皇室战争,他抽到了一种地狱飞龙,很开心.假设地域飞龙会对距离为d的敌 ...
- javascript设计模式——职责链模式
前面的话 职责链模式的定义是使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止.职责链模式的名字非常形象,一 ...
- js 哈希路由原理实现
在 js 中,有一种方法,可以在不刷新页面的情况下,页面的内容进行变更,ajax 是一种,这里介绍另一种,就是 哈希路由原理 先看一个简单的路由和页面内容关联的例子,要实现两个功能: 1.1. 浏览器 ...
- 【DevOps】团队敏捷开发系列--开山篇
随着软件发布迭代的频率越来越高,传统的「瀑布型」(开发-测试-发布)模式已经不能满足快速交付的需求.2009 年左右 DevOps 应运而生,开发运维一体化,通过自动化工具与流程让整个软件开发构建.测 ...
- Python爬虫(十)_正则表达式
本篇将介绍python正则表达式,更多内容请参考:[python正则表达式] 什么是正则表达式 正则表达式,又称规则表达式,通常被用来检索.替换那些符合某个模式(规则)的文本. 正则表达式是对字符串操 ...