http://www.lydsy.com/JudgeOnline/problem.php?id=1492

思路:

问题转变为维护一个凸包,每次转移都找凸包上的点,并更新凸壳

可以用splay维护,或者说,可以用cdq分治去维护,左半边构成的凸壳对右半边答案的影响~

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
const double eps=1e-;
double f[];
struct node{
double a,b,rate,x,y,k;
int id;
}p[],tmp[];
int n,stack[];
int read(){
int t=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
bool cmp(node a,node b){
return a.k>b.k;
}
double getk(int a,int b){
if (!b) return -1e20;
if (fabs(p[a].x-p[b].x)<eps) return 1e20;
return (p[b].y-p[a].y)/(p[b].x-p[a].x);
}
void cdq(int l,int r){
if (l==r){
f[l]=std::max(f[l],f[l-]);
p[l].y=f[l]/(p[l].a*p[l].rate+p[l].b);
p[l].x=p[l].rate*p[l].y;
return;
}
int mid=(l+r)>>;
int l1=l-,l2=mid;
for (int i=l;i<=r;i++)
if (p[i].id<=mid)
tmp[++l1]=p[i];
else
tmp[++l2]=p[i];
for (int i=l;i<=r;i++)
p[i]=tmp[i];
cdq(l,mid);
int top=;
for (int i=l;i<=mid;i++){
while (top>&&getk(stack[top-],stack[top])<getk(stack[top-],i)+eps) top--;
stack[++top]=i;
}
stack[++top]=;int j=;
for (int i=mid+;i<=r;i++){
while (j<top&&getk(stack[j],stack[j+])+eps>p[i].k) j++;
f[p[i].id]=std::max(f[p[i].id],p[stack[j]].x*p[i].a+p[stack[j]].y*p[i].b);
}
cdq(mid+,r);
l1=l,l2=mid+;
for (int i=l;i<=r;i++){
if ((((p[l1].x<p[l2].x)||(fabs(p[l1].x-p[l2].x)<eps&&p[l1].y<p[l2].y))||l2>r)&&l1<=mid) tmp[i]=p[l1++];
else tmp[i]=p[l2++];
}
for (int i=l;i<=r;i++)
p[i]=tmp[i];
}
int main(){
scanf("%d",&n);scanf("%lf",&f[]);
for (int i=;i<=n;i++){
scanf("%lf%lf%lf",&p[i].a,&p[i].b,&p[i].rate);
p[i].k=-p[i].a/p[i].b;
p[i].id=i;
}
std::sort(p+,p++n,cmp);
cdq(,n);
printf("%.3lf",f[n]);
}

Splay代码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
const double eps=1e-;
int fa[],ch[][];
double lk[],rk[];
double x[],y[],f[],rate[],a[],b[];
int n,root;
int read(){
int t=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
void rotate(int x,int &rt){
int y=fa[x],z=fa[y],l,r;
if (ch[y][]==x) l=;else l=;r=l^;
if (y!=rt){
if (ch[z][]==y) ch[z][]=x;
else ch[z][]=x;
}else rt=x;
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];ch[x][r]=y;
}
void splay(int x,int &rt){
while (x!=rt){
int y=fa[x],z=fa[y];
if (y!=rt){
if ((ch[y][]==x)^(ch[z][]==y)) rotate(x,rt);
else rotate(y,rt);
}
rotate(x,rt);
}
}
void insert(int &k,int Fa,int id){
if (!k){
k=id;
fa[k]=Fa;
return;
}
if (x[k]+eps>=x[id]) insert(ch[k][],k,id);
else insert(ch[k][],k,id);
}
double getk(int i,int j){
if (fabs(x[i]-x[j])<eps) return -1e9;
else return (y[i]-y[j])/(x[i]-x[j]);
}
int pre(int rt){
int k=ch[rt][];int tmp=k;
while (k){
if (lk[k]+eps>=getk(k,rt)) tmp=k,k=ch[k][];
else k=ch[k][];
}
return tmp;
}
int suc(int rt){
int k=ch[rt][];int tmp=k;
while (k){
if (rk[k]<=eps+getk(k,rt)) tmp=k,k=ch[k][];
else k=ch[k][];
}
return tmp;
}
void updata(int k){
splay(k,root);
if (ch[k][]){
int left=pre(root);
splay(left,ch[k][]);ch[left][]=;
lk[k]=rk[left]=getk(k,left);
}else lk[k]=1e9;
if (ch[k][]){
int right=suc(root);
splay(right,ch[k][]);ch[right][]=;
lk[right]=rk[k]=getk(k,right);
}else rk[k]=-1e9;
if (lk[k]<=rk[k]+eps){
root=ch[k][];
ch[root][]=ch[k][];
fa[ch[k][]]=root;
fa[root]=;
rk[root]=lk[ch[k][]]=getk(root,ch[k][]);
}
}
int find(int k,double slop){
if (!k) return ;
if (lk[k]+eps>=slop&&slop+eps>=rk[k]){
return k;
}
if (slop+eps>lk[k]) return find(ch[k][],slop);
else return find(ch[k][],slop);
}
int main(){
n=read();scanf("%lf",&f[]);
for (int i=;i<=n;i++){
scanf("%lf%lf%lf",&a[i],&b[i],&rate[i]);
}
for (int i=;i<=n;i++){
int j=find(root,-a[i]/b[i]);
f[i]=std::max(f[i-],x[j]*a[i]+b[i]*y[j]);
y[i]=f[i]/(a[i]*rate[i]+b[i]);
x[i]=y[i]*rate[i];
insert(root,,i);
updata(i);
}
printf("%.3f\n",f[n]);
}

BZOJ 1492 货币兑换Cash的更多相关文章

  1. BZOJ 1492 货币兑换 Cash CDQ分治

    这题n2算法就是一个维护上凸包的过程. 也可以用CDQ分治做. 我的CDQ分治做法和网上的不太一样,用左边的点建立一个凸包,右边的点在上面二分. 好处是思路清晰,避免了凸包的插入删除,坏处是多了一个l ...

  2. BZOJ 1492 货币兑换

    Description Input 第一行两个正整数\(N,S\),分别表示小Y 能预知的天数以及初始时拥有的钱数. 接下来\(N\)行,第\(K\)行三个实数\(A_{K},B_{K},Rate_{ ...

  3. BZOJ 1492 [NOI2007] - cash

    Description 最初你有 S 块钱, 有 N 天给你来兑换货币, 求最大获利. 一共只有两种货币 A , B . 对于每一天, 给定 3 个系数 A[i], B[i], Rate[i] A[i ...

  4. BZOJ 1492 货币兑换 cdq分治或平衡树维护凸包

    题意:链接 方法:cdq分治或平衡树维护凸包 解析: 这道题我拒绝写平衡树的题解,我仅仅想说splay不要写挂,insert边界条件不要忘.del点的时候不要脑抽d错.有想写平衡树的去看140142或 ...

  5. 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的数量. 然后就很明显了...平衡 ...

  6. 【BZOJ】【1492】【NOI207】货币兑换Cash

    DP/CDQ分治 orz Hzwer copy了下他的代码……结果在while(j<top......)这一句中把一个括号的位置打错了……找了我一个多小时才找到TAT 很神奇……顺便贴下CDQ的 ...

  7. bzoj千题计划237:bzoj1492: [NOI2007]货币兑换Cash

    http://www.lydsy.com/JudgeOnline/problem.php?id=1492 dp[i] 表示 第i天卖完的最大收益 朴素的dp: 枚举从哪一天买来的在第i天卖掉,或者是不 ...

  8. 1492: [NOI2007]货币兑换Cash【CDQ分治】

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

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

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

随机推荐

  1. PHP上传文件出现文件名被截掉第一个字符的问题

    最近用PHP做了一个简单的上传功能,结果出现了一个意想不到的问题.我上传的文件,在获取$_FILES的时候发现文件名的第一个字符被截掉了,因为最开始上传的一直是数字或者字母为名称的文档,也没有太在意这 ...

  2. Servlet问题:servlet cannot be resolved to a type解决办法

    工程里的路径权限高,并且eclipse并到classpath里寻找jar位置,所以我就到我的java项目里 项目名-->右键 Property-->选择 Java Build Path-- ...

  3. android后台截屏实现(2)--screencap源码修改

    首先找到screencap类在Android源码中的位置,/442/frameworks/base/cmds/screencap/screencap.cpp 源码如下: /* * Copyright ...

  4. hdu 4940 无源汇有上下界最大流

    /* <img src="http://img.blog.csdn.net/20140823174212937?watermark/2/text/aHR0cDovL2Jsb2cuY3N ...

  5. 菜鸟玩云计算之十六:Ubuntu14.04上创建的虚拟机迁移到RHEL6.4

    菜鸟玩云计算之十六:Ubuntu14.04上创建的RHEL6.4虚拟机迁移到RHEL6.4主机上 RHEL6.4 Server作为虚拟机的HOST,执行以下的命令检查配置和安装相关软件: # egre ...

  6. 将apk文件添加到Android模拟器(AVD)中运行

    apk不同exe和jar文件,apk需要在安卓系统中运行,单有一个apk文件还是没用,不能直接拖进AVD中(当然可以直接放到安卓系统的手机中) 由于我们的eclipse大都是已经安装好,解压直接使用的 ...

  7. 服务 远程服务 AIDL 进程间通讯 IPC 深化

    示例 aidl接口文件 package com.bqt.aidlservice.aidl; parcelable Person;  package com.bqt.aidlservice.aidl; ...

  8. 深入理解PreparedStatement和Statement

    执行SQL语句时,就执行一次使用Statement对象,当一句SQL语句要执行多次,这时使用PrepareStatement.虽然使用PrepareStatement执行一次时非内存,但是,在后来的执 ...

  9. document.onclick vs window.onclick

    The JavaScript Window object is the highest level JavaScript object which corresponds to the web bro ...

  10. html hack 列表

    <!--[if !IE]><!--> 除IE外都可识别 <!--<![endif]--> <!--[if IE]> 所有的IE可识别 <![ ...