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券).每个持有金券的顾客都有一个自己的帐户.金券的数目可以是一个 ...
随机推荐
- C#对SQLite、Access数据库操作的封装,很好用的~
1.对SQLite的封装: using System; using System.Collections.Generic; using System.Linq; using System.Text; ...
- 解决WebSocket兼容ie浏览器版本问题
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7942323.html 在使用Netty进行WebSocket开发时,测试发现:ie 11系列个别低版本连接W ...
- E:I Think I Need a Houseboat-poj
E:I Think I Need a Houseboat 总时间限制: 1000ms 内存限制: 65536kB 描述 Fred Mapper is considering purchasing ...
- VMWare安装Win10虚拟机
这两天突发奇想安了个win10虚拟机,在安装的过程中还遇到了不少麻烦,所以在此与大家分享下. 首先我们用VMWare12来安装,VMWare已经更新到14但是不太稳定,所以为了保险起见还是用12吧. ...
- Bootstrap-datepicker3官方文档中文翻译---概述(原版翻译 http://bootstrap-datepicker.readthedocs.io/en/latest/index.html)
bootstrap-datepicker Bootstrap-datepicker 提供了一个拥有Bootstrap样式的弹性Datepicker控件 Requirements/使用要求 Bootst ...
- MySQL 性能优化的最佳20多条经验分享(一)(转)
当我们去设计数据库表结构,对操作数据库时(尤其是查表时的SQL语句),我们都需要注意数据操作的性能.这里,我们不会讲过多的SQL语句的优化,而只是针对MySQL这一Web应用最多的数据库.希望下面的这 ...
- 分布式服务Dubbo+Zookeeper安全认证
前言 由于之前的服务都是在内网,Zookeeper集群配置都是走的内网IP,外网不开放相关端口.最近由于业务升级,购置了阿里云的服务,需要对外开放Zookeeper服务. 问题 Zookeeper+d ...
- selenium webdriver使用click一直失效问题的几种解决方法
想要爬取动态网页,很莫名的click失效.被这个问题困扰了很久,基本上把网上提到的所有方法试遍了,最终终于有个方法成功了,在这里总结一下. 这是我想要点击的网页,初始时实在0.5km上,它的class ...
- inotify软件部署及实时同步
声明:博主使用的是CentOS6.9的系统 参考资料: https://github.com/rvoicilas/inotify-tools/wiki http://www.ibm.com/devel ...
- python爬虫(五)_urllib2:Get请求和Post请求
本篇将介绍urllib2的Get和Post方法,更多内容请参考:python学习指南 urllib2默认只支持HTTP/HTTPS的GET和POST方法 urllib.urlencode() urll ...