斜率优化(CDQ分治,Splay平衡树):BZOJ 1492: [NOI2007]货币兑换Cash
Description

Input
Output
Sample Input
1 1 1
1 2 2
2 2 3
Sample Output
HINT
测试数据设计使得精度误差不会超过10-7。
对于40%的测试数据,满足N ≤ 10;
对于60%的测试数据,满足N ≤ 1 000;
对于100%的测试数据,满足N ≤ 100 000;
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const double eps=1e-;
const int maxn=;
struct Node{
double a,b,r,x,y,k;
int id;
}d[maxn],t[maxn];
double f[maxn];
int st[maxn],cnt,n;
double Abs(double a){return a>?a:-a;}
double K(int a,int b){
if(Abs(d[a].x-d[b].x)<eps)return 1e20;
return (d[a].y-d[b].y)/(d[a].x-d[b].x);
}
void Solve(int l,int r){
if(l==r){
f[l]=max(f[l],f[l-]);
d[l].y=f[l]/(d[l].r*d[l].a+d[l].b);
d[l].x=d[l].y*d[l].r;
return;
}
int mid=(l+r)>>,t1=l,t2=mid+;
for(int i=l;i<=r;i++){
if(d[i].id<=mid)
t[t1++]=d[i];
else
t[t2++]=d[i];
}
for(int i=l;i<=r;i++)d[i]=t[i];
Solve(l,mid);
cnt=;
for(int i=l;i<=mid;i++){
while(cnt>&&K(i,st[cnt])-K(st[cnt],st[cnt-])>=eps)cnt--;
st[++cnt]=i;
}
int fir=;
for(int i=mid+;i<=r;i++){
while(fir<cnt&&K(st[fir+],st[fir])-d[i].k>=eps)fir++;
f[d[i].id]=max(f[d[i].id],d[st[fir]].x*d[i].a+d[st[fir]].y*d[i].b);
}
Solve(mid+,r);
t1=l;t2=mid+;
for(int i=l;i<=r;i++){
if(t2==r+||(d[t2].x-d[t1].x>=eps||Abs(d[t2].x-d[t1].x)<eps&&d[t2].y-d[t1].y>=eps)&&t1<=mid)
t[i]=d[t1++];
else
t[i]=d[t2++];
}
for(int i=l;i<=r;i++)
d[i]=t[i];
} bool cmp(Node a,Node b){
return a.k>b.k;
}
int main(){
scanf("%d%lf",&n,&f[]);
for(int i=;i<=n;i++){
scanf("%lf%lf%lf",&d[i].a,&d[i].b,&d[i].r);
d[i].k=-d[i].a/d[i].b;
d[i].id=i;
}
sort(d+,d+n+,cmp);
Solve(,n);
printf("%.3lf\n",f[n]);
return ;
}
这里还有Splay。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const double eps=1e-;
const double INF=1e20;
const int maxn=;
int ch[maxn][],fa[maxn],rt,tot,n;
double X[maxn],Y[maxn],lk[maxn],rk[maxn],ans;
double fabs(double x){return (x>)?x:-x;}
void Rotate(int x){
int y=fa[x],g=fa[y],c=ch[y][]==x;
ch[y][c]=ch[x][c^];fa[ch[y][c]]=y;
ch[x][c^]=y;fa[y]=x;fa[x]=g;
if(g)ch[g][ch[g][]==y]=x;
} void Splay(int x,int g=){
for(int y;(y=fa[x])!=g;Rotate(x))
if(fa[y]!=g)Rotate((ch[fa[y]][]==y)==(ch[y][]==x)?y:x);
if(!g)rt=x;
} double Get_K(int j,int k){
if(fabs(X[j]-X[k])<=eps)return INF;
else return (Y[j]-Y[k])/(X[j]-X[k]);
} int Get_Prev(){
int p=ch[rt][],ret=p;
while(p){
if(Get_K(rt,p)+eps>=lk[p])p=ch[p][];
else ret=p,p=ch[p][];
}
return ret;
} int Get_Succ(){
int p=ch[rt][],ret=p;
while(p){
if(Get_K(p,rt)<=rk[p]+eps)p=ch[p][];
else ret=p,p=ch[p][];
}
return ret;
} void Insert(int &r,int pre,int p){
if(r==){r=p;fa[p]=pre;return;}
if(X[p]<=X[r]+eps)Insert(ch[r][],r,p);
else Insert(ch[r][],r,p);
} void Update(int p){
Splay(p);
if (ch[p][]){
int l=Get_Prev();
Splay(l,p);ch[l][]=;
lk[p]=rk[l]=Get_K(p,l);
}
else lk[p]=INF;
if (ch[p][]){
int r=Get_Succ();
Splay(r,p); ch[r][]=;
rk[p]=lk[r]=Get_K(r,p);
}
else rk[p]=-INF;
if (lk[p]<=rk[p]+eps){
rt=ch[p][]; ch[rt][]=ch[p][]; fa[ch[p][]]=rt; fa[rt]=;
rk[rt]=lk[ch[p][]]=Get_K(ch[rt][],rt);
}
} int Get_Pos(double k){
int p=rt;
while(p){
if(lk[p]+eps>=k&&k+eps>=rk[p])break;
if(lk[p]<k+eps)p=ch[p][];
else p=ch[p][];
}
return p;
} double Get_Ans(double a,double b){
int p=Get_Pos(-b/a);
return a*Y[p]+b*X[p];
} int main(){
#ifndef ONLINE_JUDGE
freopen("cash.in","r",stdin);
freopen("cash.out","w",stdout);
#endif
double a,b,rate;
scanf("%d%lf",&n,&ans);
for(int i=;i<=n;i++){
scanf("%lf%lf%lf",&a,&b,&rate);
if(i!=)ans=max(ans,Get_Ans(a,b));
X[i]=ans/(rate*a+b);
Y[i]=X[i]*rate;
Insert(rt,,i);
Update(i);
}
printf("%.3f\n",ans);
return ;
}
斜率优化(CDQ分治,Splay平衡树):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
Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下 简称B券).每个持有金券的顾客都有一个自己的帐户.金券的数目可以是一个 ...
- BZOJ.1492.[NOI2007]货币兑换(DP 斜率优化 CDQ分治/Splay)
BZOJ 洛谷 如果某天能够赚钱,那么一定会在这天把手上的金券全卖掉.同样如果某天要买,一定会把所有钱花光. 那么令\(f_i\)表示到第\(i\)天所拥有的最多钱数(此时手上没有任何金券),可以选择 ...
- BZOJ 1492: [NOI2007]货币兑换Cash [CDQ分治 斜率优化DP]
传送门 题意:不想写... 扔链接就跑 好吧我回来了 首先发现每次兑换一定是全部兑换,因为你兑换说明有利可图,是为了后面的某一天两种卷的汇率差别明显而兑换 那么一定拿全利啊,一定比多天的组合好 $f[ ...
- bzoj 1492 [NOI2007]货币兑换Cash(斜率dp+cdq分治)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1492 [题意] 有AB两种货币,每天可以可以付IPi元,买到A券和B券,且A:B= ...
- 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
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1492 题解: 斜率优化DP,CDQ分治 定义$DP[i]$为第i天结束后的最大收益. 由于题 ...
- BZOJ 1492 [NOI2007]货币兑换Cash:斜率优化dp + cdq分治
传送门 题意 初始时你有 $ s $ 元,接下来有 $ n $ 天. 在第 $ i $ 天,A券的价值为 $ A[i] $ ,B券的价值为 $ B[i] $ . 在第 $ i $ 天,你可以进行两种操 ...
随机推荐
- 各大浏览器CSS Hack收集
各大浏览器CSS Hack收集 >>>>>>>>>>>>>>>>>>>>> ...
- 网站出现 HTTP 错误 401.2 - 未经授权:访问由于服务器配置被拒绝
原因:关闭了匿名身份验证 解决方案: 在开始菜单中输入运行->inetmgr,打开站点属性->目录安全性->身份验证和访问控制->选中"启用匿名访问",输入 ...
- 分享:带波形的语音播放工具(wavesurfer-js)
项目名称:wavesurfer-js github地址:https://github.com/katspaugh/wavesurfer.js 官网地址:http://wavesurfer-js.org ...
- C# DateTime
//c datetime 格式化DateTime dt = DateTime.Now;Label1.Text = dt.ToString();//2005-11-5 13:21:25Label2.Te ...
- 【BZOJ2741】【块状链表+可持久化trie】FOTILE模拟赛L
Description FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 .. ...
- C++ 语法规则
C++ 中的布尔类型:布尔类型只占用一个bit ,但是如果连续定义多个布尔类型时,编译器可能会多个布尔类型定义在一起.true 编译器用1来表示.false 编译器用0来表示. 将一个其他类型的数 ...
- Oracle数据库之PL/SQL包
Oracle数据库之PL/SQL包 1. 简介 包(PACKAGE)是一种数据对象,它是一组相关过程.函数.变量.常量和游标等PL/SQL程序设计元素的组合,作为一个完整的单元存储在数据库中,用名称来 ...
- 源码来袭!!!基于jquery的ajax分页插件(demo+源码)
前几天打开自己的博客园主页,无意间发现自己的园龄竟然有4年之久了.可是看自己的博客列表却是空空如也,其实之前也有写过,但是一直没发布(然而好像并没有什么卵用).刚开始学习编程时就接触到博客园,且在博客 ...
- PHPCMS二层栏目调用
{pc:content action="category" catid="0" num="25" siteid="$siteid& ...
- openerp 产品图片的批量写入
Write a short python script which loops over the image files, encode with base64 and write to OpenER ...