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. bootstrap 动态添加验证项和取消验证项

    bootstrap 中的bootstrapValidator可以对前端的数据进行验证,但是有的时候我们需要动态的添加验证,这样需要我们动态的对bootstrapValidator的内容做修改. 传统的 ...

  2. HDU-1428(记忆化搜索)

    Problem Description LL 最近沉迷于AC不能自拔,每天寝室.机房两点一线.由于长时间坐在电脑边,缺乏运动.他决定充分利用每次从寝室到机房的时间,在校园里散散步.整个HDU 校园呈方 ...

  3. Java程序员在用的大数据工具,MongoDB稳居第一!

    据日前的一则大数据工具使用情况调查,我们知道了Java程序猿最喜欢用的大数据工具. 问题:他们最近一年最喜欢用什么工具或者是框架? 受访者可以选择列表中的选项或者列出自己的,本文主要关心的是大数据工具 ...

  4. 我所理解的设计模式(C++实现)——策略模式(Strategy Pattern)

    概述: 每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法. 而策略模式就是对算法进行包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理.策 ...

  5. 远程连接mysql

    win系统下,连接别人的mysql或者让别人链接自己的mysql: 打开命令行cmd 进入mysql: mysql -u root -p mysql>use mysql;  mysql>s ...

  6. 【KMP】剪花布条

    KMP算法 又水了一题.算是巩固复习吧. Problem Description 一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案.对于给定的花布条和小饰条,计算一下能从花布条中尽 ...

  7. 根据请求头跳转判断Android&iOS

    if(navigator.userAgent.match(/Android/i)) { window.location = 'http://apk.hiapk.com/m/downloads?id=c ...

  8. CSS3: box-sizing 属性的简单认识

    定义和用法: box-sizing 属性允许您以特定的方式定义匹配某个区域的特定元素. 默认值:content-box; 继承性:无: css版本:css3 语法:box-sizing: conten ...

  9. [Angular 2] Using Promise to Http

    You can also use Promise for http: So for the service, you need to call toPromise() method: getVehic ...

  10. Linux - Eclipse CDT + GCC 安装(2014.10.2)

    Eclipse CDT + GCC 安装 (2014.10.2) 本文地址:http://blog.csdn.net/caroline_wendy 1. 安装Eclipse,在官方站点下载Eclips ...