好题+神题,首先肯定是dp,我们设f[i]为到第i天能获得的最多的B卷(设获得的钱数亦可)
由题目hint可知,要么全买要么全卖,我们有
f[i]=max(maxmoney,f[j]*b[i]+f[j]*rate[j]*a[i]))/(a[i]*rate[i]+b[i]),
这式子一看就是斜率优化,maxmoney可以先不管它
考虑决策j,k不妨设j<k,如果决策k优于j那么有
f[j]*b[i]+f[j]*rate[j]*a[i]<f[k]*b[i]+f[k]*rate[k]*a[i]
可以得到(f[k]*rate[k]-f[j]*rate[j])/(f[k]-f[j])>-b[i]/a[i]
我们设每个点是(f[k],f[k]*rate[k]),G(j,k)=(f[k]*rate[k]-f[j]*rate[j])/(f[k]-f[j])就是斜率
很明显我们要维护一个上凸壳,但这里我们不能用单调队列,因为后面不是单调的
可以用平衡树维护,但是我们观察这个式子
后面状态不会对前面状态产生影响(修改独立),并且不强制在线
于是我们可以用cdq分治来解决这个问题,我们还是根据天数顺序(状态)进行分治
分治过程中关键就是算[l,mid]部分整体对后面[mid+1.r]部分的影响
要能快速计算需要两个东西,首先我们要维护一个凸壳,
其次我们要按照单调的顺序处理后面部分的-b[]/a[],这样我们可以用单调队列来做,
我们可以先对-b[]/a[]降序排序(上凸线相邻两点间的斜率是递减的)
然后先递归处理处于左边(状态时[l,mid])的点,
在对一个区间都处理完毕之后,我们对这之间的点x为第一关键字排序,y为第二关键字排序
这样我们就能得到就得到了[l,mid]这部分状态排好序的点,然后我们维护单调队列,算出[l,mid]整体对[mid+1,r]的影响
然后我们再递归处理右边,完来之后再排序对[l,r]整体排序
在处理排序的时候,很很明显我们可以用归并排序,这样每次递归时处理得复杂度都是O(L) L是区间长度
所以根据主定理,T(n)=2T(n/2)+O(n) 复杂度是O(nlogn);
注意这道题凸线会挂精度,到底在什么时候要保留精度呢?请求指教

 const eps=1e-9;
type node=record
a,b,ra,k,x,y:double;
po:longint;
end; var a,b:array[..] of node;
f:array[..] of double;
q:array[..] of longint;
i,n:longint; function getk(x,y:longint):double;
begin
if abs(a[y].x-a[x].x)<eps then exit(1e21);
exit((a[y].y-a[x].y)/(a[y].x-a[x].x));
end; function cmp(a,b:node):boolean;
begin
exit((a.x<b.x) or (abs(a.x-b.x)<eps) and (a.y<b.y));
end; function max(a,b:double):double;
begin
if a>b then exit(a) else exit(b);
end; procedure swap(var a,b:node);
var c:node;
begin
c:=a;
a:=b;
b:=c;
end; procedure sort(l,r:longint);
var i,j:longint;
x:double;
begin
i:=l;
j:=r;
x:=a[(l+r) shr ].k;
repeat
while x<a[i].k do inc(i);
while a[j].k<x do dec(j);
if not(i>j) then
begin
swap(a[i],a[j]);
inc(i);
dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end; procedure cdq(l,r:longint);
var m,i,l1,l2,t,j:longint;
begin
if l=r then
begin
f[l]:=max(f[l],f[l-]); //这里f[]代表的是钱数
a[l].x:=f[l]/(a[l].ra*a[l].a+a[l].b); //获得B券的数目
a[l].y:=a[l].x*a[l].ra;
exit;
end;
m:=(l+r) shr ;
l1:=l; l2:=m+;
for i:=l to r do //先处理左部分的状态
if a[i].po<=m then
begin
b[l1]:=a[i];
inc(l1);
end
else begin
b[l2]:=a[i];
inc(l2);
end;
for i:=l to r do a[i]:=b[i];
cdq(l,m); t:=;
for i:=l to m do
begin
while (t>) and (getk(q[t-],q[t])<getk(q[t-],i)+eps) do dec(t); //维护凸壳
inc(t); q[t]:=i;
end;
j:=;
for i:=m+ to r do
begin
while (j<t) and (getk(q[j],q[j+])+eps>a[i].k) do inc(j); //计算影响(就是找第一个小于的斜率的左端点)
f[a[i].po]:=max(f[a[i].po],a[q[j]].x*a[i].b+a[q[j]].y*a[i].a);
end; cdq(m+,r);
l1:=l; l2:=m+;
for i:=l to r do //归并排序
if ((l2>r) or cmp(a[l1],a[l2])) and (l1<=m) then
begin
b[i]:=a[l1];
inc(l1);
end
else begin
b[i]:=a[l2];
inc(l2);
end; for i:=l to r do a[i]:=b[i];
end; begin
readln(n,f[]);
for i:= to n do
begin
readln(a[i].a,a[i].b,a[i].ra);
a[i].k:=-a[i].b/a[i].a;
a[i].po:=i;
end;
sort(,n);
cdq(,n);
writeln(f[n]::);
end.

bzoj1492的更多相关文章

  1. 【bzoj1492】 NOI2007—货币兑换Cash

    http://www.lydsy.com/JudgeOnline/problem.php?id=1492 (题目链接) 题意 两种金券,金券按照比例交易:买入时,将投入的资金购买比例为$rate[i] ...

  2. 【BZOJ1492】【NOI2007】货币兑换(动态规划,CDQ分治,Splay)

    [BZOJ1492][NOI2007]货币兑换(动态规划,CDQ分治,Splay) 题面 BZOJ 洛谷 Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券 ...

  3. [BZOJ1492][NOI2007]货币兑换Cash(斜率优化+CDQ分治)

    1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 5838  Solved: 2345[Submit][Sta ...

  4. 【BZOJ1492】货币兑换Cash(CDQ分治)

    题意: 小 Y 最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A 纪 念券(以下简称 A 券)和 B 纪念券(以下简称 B 券).每个持有金券的顾客都有 一个自己的帐户.金券的数目可以是一 ...

  5. BZOJ1492:[NOI2007]货币兑换 (CDQ分治+斜率优化DP | splay动态维护凸包)

    BZOJ1492:[NOI2007]货币兑换 题目传送门 [问题描述] 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和B纪念券(以下简称B券).每个持有金券的 ...

  6. [BZOJ1492] [NOI2007] 货币兑换Cash(cdq分治+斜率优化)

    [BZOJ1492] [NOI2007] 货币兑换Cash(cdq分治+斜率优化) 题面 分析 dp方程推导 显然,必然存在一种最优的买卖方案满足:每次买进操作使用完所有的人民币:每次卖出操作卖出所有 ...

  7. BZOJ1492: [NOI2007]货币兑换Cash

    设$x_j$,$y_j$为第$j$天能买的A,B券数量,$f_i$为第$i$天的最大收益.$f_i=\max_{1\le j<i}a_ix_j+b_iy_j$,最大化$f_i$即找一个点$(x_ ...

  8. bzoj1492 斜率优化|cdq分治

    #include <stdio.h> #include <bitset> #include <string.h> #include <stack> #i ...

  9. 【BZOJ-1492】货币兑换Cash DP + 斜率优化 + CDQ分治

    1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 3396  Solved: 1434[Submit][Sta ...

随机推荐

  1. ios - cordova(phoneGap)

    安装教程 下载 node.js. http://nodejs.org/ 下载后,直接安装就可以了. 安装 Cordova工具, $ sudo npm install -g cordova 创建APP: ...

  2. Windows下lex 与 yacc的使用(2)

                                 Windows下lex 与 yacc的使用                                                   ...

  3. dubbo监控活跃线程数

    telnet对应dubbo服务的ip+端口号 status -l 其中的active就是当前的活跃线程数 通过程序定时探测写入DB,再查询渲染出来就好了 监控报警,如果已经有监控平台,可以通过一定的规 ...

  4. 11_Servlet基础知识

    [概念] Servlet通常被称为服务端小程序,是运行在服务端的程序,用于处理及相应客户端的请求. Servlet是用java语言开发网页动态资源的技术. [特点] 1.Servlet是个特殊的Jav ...

  5. .NET小项目之MyKtv(歌曲播放功能实现)

    在KTV点歌系统中我们根据需求获取到歌手的歌曲信息,点击歌手的歌曲将其添加到一点歌曲列表中看似简单的一个操作其实涉及很多内容,这也是写这篇Blog的目的—分析歌曲播放的原理. 原理分析 我们应该清楚, ...

  6. QQ登录网站接入

    QQ网站登录是一个非常常用的功能,网上有很多的资料,在此只做一个整理: QQ登录接入也在不断的升级,目前我发布的是2.1,很多资料里显示的那些繁杂的步骤已经不需要了: 第一步需要先申请,申请地址如下: ...

  7. python基础学习(二)--函数

    return返回值: python函数都有返回值,函数体内无return,默认返回值None, 函数参数: 1.普通参数 严格按照顺序,将实际参数赋值给形式参数,一一对应. 例: def send(x ...

  8. python函数的返回值 讲解

    我们一起来聊聊python函数返回值的特殊情况,之前我也碰到过类似方面的问题,到后来查阅了一些资料后,发现原来是这样. 首先,写函数的时候,一定要写函数的文档,这样方便我们识别函数是做什么的.我记得很 ...

  9. 几个.net的GUI控件库

    https://github.com/firstfloorsoftware/mui http://wpftoolkit.codeplex.com/ https://github.com/fluentr ...

  10. delphi xe5 android 控制蓝牙

    本文部分内容摘自: http://www.pclviewer.com/android/用以下代码中的接口实现控制蓝牙的开.关及详细信息 unit Androidapi.JNI.BluetoothAda ...