P4027 [NOI2007]货币兑换
首先有一个显然的贪心,每次操作都要做到底,为了最优不会出现只卖一部分或者只买一部分的操作
所以设 $f[i]$ 表示前 $i$ 天得到的最大价值,那么对于每一个 $i$,枚举所有 $j<i$,意思就是第 $j$ 天全部买入,第 $i$ 天全部卖出
显然如果知道 $f[j]$,那么就知道第 $j$ 天买入多少
设 $A$ 买了 $X$, $B$ 买了 $Y$,那么 $f[i]=a[i]*X+b[i]*Y$
因为 $X,Y$ 只和 $j$ 有关,显然可以斜率优化
具体就是 $-a[i]*X+f[i]=b[i]*Y$,同除一个 $b[i]$,变成 $-a[i]/b[i]*X+f[i]/b[i]=Y$
那么 $k=-a[i]/b[i],x=X,b=f[i]/b[i],y=Y$
自己推一下,容易得出 $X_i=f[i]*r[i]/(a[i]*r[i]+b[i]),Y_i=f[i]/(a[i]*r[i]+b[i])$
然后因为 $k,x$ 都不单调,所以要用 $CDQ$ 搞
先按斜率排序,然后 $CQD$ 分治之前按下标拆成两部分,这个具体还是看代码吧...
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
typedef double db;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=2e5+,INF=1e9+;
const db eps=1e-;
int n,S;
db f[N];
struct dat{
db k,x,y,a,b,r;
int id;
inline bool operator < (const dat &tmp) const {
return k<tmp.k;
}
}T[N],tmp[N];
inline db slope(int i,int j)//求斜率维护凸包
{
if(fabs(T[i].x-T[j].x)<=eps) return T[i].y>T[j].y ? INF : -INF;
return (T[i].y-T[j].y)/(T[i].x-T[j].x);
}
inline db Cross(db xa,db ya,db xb,db yb) { return xa*yb-xb*ya; }//用叉积维护凸包会更快
inline void merge(int l,int r,int mid)//按x归并排序
{
int pl=l,pr=mid+;
for(int p=l;p<=r;p++)
{
if(pl<=mid&& (pr>r||T[pl].x<T[pr].x/*+eps*/) ) tmp[p]=T[pl++];
else tmp[p]=T[pr++];
}
for(int p=l;p<=r;p++) T[p]=tmp[p];
}
int Q[N];//栈,维护凸包
void CDQ(int l,int r)
{
if(l==r)//到了最底下,此时f[l]已经被所有f[j](j<l)更新完毕
{
f[l]=max(f[l],f[l-]);//这一天可以不操作
T[l].y=f[l]/(T[l].a*T[l].r+T[l].b),T[l].x=T[l].y*T[l].r;
//更新f[l]完才求X[l],Y[l]
return;
}
int mid=l+r>>,pl=l,pr=mid+,top=;
for(int p=l;p<=r;p++)//按下标分开
{
if(T[p].id<=mid) tmp[pl++]=T[p];
else tmp[pr++]=T[p];
}
for(int p=l;p<=r;p++) T[p]=tmp[p];
CDQ(l,mid); Q[]=;//先处理左边
for(int i=l;i<=mid;i++)//此时左边全部更新完毕,可以维护左边构成的凸包了
//注意此时左边的T[i].x是有序的,因为每次CDQ结束都会merge
{
while( top> &&
Cross(T[i].x-T[Q[top-]].x,T[i].y-T[Q[top-]].y,T[Q[top]].x-T[Q[top-]].x,T[Q[top]].y-T[Q[top-]].y)<= ) top--;
Q[++top]=i;
}
for(int i=mid+;i<=r;i++)//用左边构成的凸包更新右边,此时右边的斜率是有序的
{
while( top> && /*T[i].k>=slope(Q[top-1],Q[top])+eps*/ //注释的内容和下一行是等价的,注意eps
Cross(,T[i].k,T[Q[top]].x-T[Q[top-]].x,T[Q[top]].y-T[Q[top-]].y)<= ) top--;
int j=Q[top]; f[T[i].id]=max(f[T[i].id],T[j].x*T[i].a+T[j].y*T[i].b);//更新
}
CDQ(mid+,r); merge(l,r,mid);//处理右边后按x排序
}
int main()
{
n=read(); f[]=read();
for(int i=;i<=n;i++)
{
scanf("%lf%lf%lf",&T[i].a,&T[i].b,&T[i].r);
T[i].k=-T[i].a/T[i].b; T[i].id=i;//初始化
}
sort(T+,T+n+); CDQ(,n);//先按k排序再CDQ
printf("%.3lf",f[n]);
return ;
}
P4027 [NOI2007]货币兑换的更多相关文章
- P4027 [NOI2007]货币兑换(斜率优化dp+cdq分治)
P4027 [NOI2007]货币兑换 显然,如果某一天要买券,一定是把钱全部花掉.否则不是最优(攒着干啥) 我们设$f[j]$为第$j$天时用户手上最多有多少钱 设$w$为花完钱买到的$B$券数 $ ...
- 洛谷 P4027 [NOI2007]货币兑换 解题报告
P4027 [NOI2007]货币兑换 题目描述 小 \(Y\) 最近在一家金券交易所工作.该金券交易所只发行交易两种金券:\(A\) 纪念券(以下简称 \(A\) 券)和 \(B\) 纪念券(以下简 ...
- 洛谷P4027 [NOI2007]货币兑换
P4027 [NOI2007]货币兑换 算法:dp+斜率优化 题面十分冗长,题意大概是有一种金券每天价值会有变化,你可以在某些时间点买入或卖出所有的金券,问最大收益 根据题意,很容易列出朴素的状态转移 ...
- LOJ 2353 & 洛谷 P4027 [NOI2007]货币兑换(CDQ 分治维护斜率优化)
题目传送门 纪念一下第一道(?)自己 yy 出来的 NOI 题. 考虑 dp,\(dp[i]\) 表示到第 \(i\) 天最多有多少钱. 那么有 \(dp[i]=\max\{\max\limits_{ ...
- 洛谷P4027 [NOI2007]货币兑换(dp 斜率优化 cdq 二分)
题意 题目链接 Sol 解题的关键是看到题目里的提示... 设\(f[i]\)表示到第\(i\)天所持有软妹币的最大数量,显然答案为\(max_{i = 1}^n f[i]\) 转移为\(f_i = ...
- LUOGU P4027 [NOI2007]货币兑换 (斜率优化+CDQ分治)
传送门 解题思路 题目里有两句提示一定要看清楚,要不全买要不全卖,所以dp方程就比较好列,f[i]=max(f[j]*rate[j]*a[i])/(rate[j]*a[j]+b[j])+(f[j]*b ...
- 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的数量. 然后就很明显了...平衡 ...
- bzoj1492[NOI2007]货币兑换Cash cdq分治+斜率优化dp
1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 5541 Solved: 2228[Submit][Sta ...
- cdq分治(hdu 5618 Jam's problem again[陌上花开]、CQOI 2011 动态逆序对、hdu 4742 Pinball Game、hdu 4456 Crowd、[HEOI2016/TJOI2016]序列、[NOI2007]货币兑换 )
hdu 5618 Jam's problem again #include <bits/stdc++.h> #define MAXN 100010 using namespace std; ...
随机推荐
- [C++] printf pitfall
printf pitfal l
- [C++] the pointer array & the array's pointer
int *p[4]------p是一个指针数组,每一个指向一个int型的int (*q)[4]---------q是一个指针,指向int[4]的数组 --> type: int(*)[4] vo ...
- chrome crx下载路径
chrome crx下载后会被删除,可在检查时粘贴出来,下载路径在: %localappdata%\Google\Chrome\User Data\Webstore Downloads 参考:http ...
- hdu 1686 KMP算法
题意: 求子串w在T中出现的次数. kmp算法详解:http://www.cnblogs.com/XDJjy/p/3871045.html #include <iostream> #inc ...
- Java中的http(网络处理)相关的库:HttpClient,HttpCore(转载)
[背景] 最近和之前,折腾了这个: [教程]模拟登陆百度之Java代码版 然后,对于Java的HttpClient,有了点了解. 现在整理如下: Java本身没有Http相关的库 Java本身,没有内 ...
- VC中CRect类的简单介绍
CRect CRect类与Windows RECT结构相似,并且还包括操作CRect对象和Windows RECT结构的成员函数.在传递LPRECT,LPCRECT或RECT结构作为参数的任何地方,都 ...
- C++派生类在构造和析构过程中做的事
(一)构造时: (1)首先调用继承关系中第一个基类(最靠左边的)的构造函数,然后第二个,第三个,以此类推 (2)然后调用成员对象的构造函数,这个顺序按照定义的顺序,与构造函数初始化列表的顺序无关. ( ...
- Android-bindService远程服务(Aidl)-传递对象
之前上一篇讲解到本地服务,本地服务只能在自身APP中Activity访问Service,调用Service里面到方法等操作 如果想A应用访问B应用里面的方法,属于跨进程调用,如果Android不特供这 ...
- WPF 实现INotifyPropertyChanged .Net Framework 4.5
自己动手写了一个基类来实现INotifyPropertyChanged接口,以后可以直接使用. using System.ComponentModel; using System.Runtime.Co ...
- VS 发布MVC网站缺少视图解决方案
VS 发布MVC网站缺少视图解决方案 mvc项目发布之后会有一些视图文件缺少,不包含在发布文件中,虽然可以直接从项目文件中直接拷贝过来,但还是想知道是什么原因,发布文件好像没有找到哪里有设置这个的地 ...