[bzoj1492]NOI2007 CASH (DP+CDQ/Splay)
来源:互联网 发布:spss mac使用教程 编辑:程序博客网 时间:2024/06/07 02:01
题目传送门
我们可以很快发现一个dp解法:可以发现答案一定是由所持有的卷的数目计算出来的,而卷的数目是可以转移的,所以令
分析对于i的两个决策j和k,可以发现决策j比决策k优当且仅当:
我们定义
即,
我们就可以斜率优化啦:
dp的第二种解法:
我们令
于是
接着我们考虑如何斜率优化,
于是我们维护平面上的点的上凸包。
解法1:Splay
用splay把所有点维护起来,每个点记录和左右两边的点的斜率。
对于每次的询问,我们用一条斜率为
对于每次插入点,首先取出
//注意下面代码为了写起来方便
//坑填好啦
//你问我CDQ在哪里? 当然是选择坑着啦
#include<bits/stdc++.h>using namespace std;const int maxn=1e5+10;const double eps=1e-8;const double inf=1e20;double X[maxn],Y[maxn];//splayint fa[maxn],ch[maxn][2];double lk[maxn],rk[maxn];int root,sz;//splayinline bool get(int x){ return (ch[fa[x]][1]==x);}inline void rotate(int x){ int old=fa[x];int oldf=fa[old];int d=get(x); fa[ch[x][d^1]]=old;ch[old][d]=ch[x][d^1]; fa[old]=x;ch[x][d^1]=old; fa[x]=oldf; if(oldf) ch[oldf][ch[oldf][1]==old]=x;}inline void splay(int x,int g=0){ for(int y;(y=fa[x])!=g;rotate(x)){ if(fa[y]!=g) rotate((get(x)==get(y))? y:x); } if(!g) root=x;}inline double getk(int j,int k){ if(fabs(X[j]-X[k]<=eps)) return inf; return (Y[j]-Y[k])/(X[j]-X[k]);}inline int get_pre(){ int p=ch[root][0],ret=p; while(p){ if(getk(root,p)+eps>=lk[p]) p=ch[p][0]; else ret=p,p=ch[p][1]; } return ret;}inline int get_suc(){ int p=ch[root][1],ret=p; while(p){ if(getk(p,root)<=rk[p]+eps) p=ch[p][1]; else ret=p,p=ch[p][0]; } return ret;}inline 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][0],r,p); else insert(ch[r][1],r,p);}inline void update(int p){ splay(p); if(ch[p][0]){ int l=get_pre(); splay(l,p); ch[l][1]=0; lk[p]=rk[l]=getk(p,l); }else lk[p]=inf; if(ch[p][1]){ int r=get_suc(); splay(r,p); ch[r][0]=0; rk[p]=lk[r]=getk(r,p); }else rk[p]=-inf; //删除凹点 if(lk[p]<rk[p]+eps){ root=ch[p][0]; ch[root][1]=ch[p][1]; fa[ch[p][1]]=root; fa[root]=0; rk[root]=lk[ch[p][1]]=getk(ch[root][1],root); }}inline int getpos(double k){ int p=root; while(p){ //切割到了凸包 if(lk[p]+eps>=k&&k+eps>=rk[p]) break; if(lk[p]<k+eps) p=ch[p][0]; else p=ch[p][1]; } return p;}inline double getans(double a,double b){ int p=getpos(-b/a); return Y[p]*a+X[p]*b;}double a,b,rate;int n;double ans;int main(int argc,const char * argv[]){ scanf("%d%lf",&n,&ans); for(int i=1;i<=n;i++){ scanf("%lf%lf%lf",&a,&b,&rate); ans=max(ans,getans(a,b)); X[i]=ans/(a*rate+b); Y[i]=X[i]*rate; insert(root,0,i);//将X,Y所代表的点插入平衡树 update(i); } printf("%.3lf",ans); return 0;}
- [bzoj1492]NOI2007 CASH (DP+CDQ/Splay)
- bzoj1492 [NOI2007]货币兑换Cash (斜率DP+cdq分治)
- [BZOJ1492][NOI2007][CDQ分治][斜率优化][DP]货币兑换Cash
- [BZOJ1492][NOI2007]货币兑换Cash-斜率优化DP-CDQ分治
- BZOJ1492: [NOI2007]货币兑换Cash 【dp + CDQ分治】
- 【cdq分治】[Noi2007] bzoj1492 货币兑换Cash
- CDQ分治维护凸包 优化dp 【NOI2007】货币兑换cash bzoj1492
- [BZOJ1492][NOI2007]货币兑换Cash(斜率优化dp+cdq分治)
- BZOJ1492:[NOI2007]货币兑换Cash (CDQ分治+斜率优化DP/平衡树维护凸壳)
- bzoj1492 [ NOI2007 ] --斜率优化DP+cdq分治
- BZOJ1492:[NOI2007]货币兑换 (CDQ分治+斜率优化DP | splay动态维护凸包)
- [BZOJ1492][NOI2007]货币兑换Cash && CDQ分治+斜率优化
- bzoj1492 [NOI2007]货币兑换Cash(斜率优化+CDQ分治)
- [bzoj1492][cdq分治][斜率优化][NOI2007]货币兑换Cash
- 1492: [NOI2007]货币兑换Cash DP+斜率优化+splay维护凸包/CDQ分治
- 【NOI2007】【BZOJ1492】货币兑换Cash
- bzoj1492: [NOI2007]货币兑换Cash
- [BZOJ1492][NOI2007]货币兑换Cash
- QT之海康解码显示小技巧 ~setUpdatesEnabled
- Tomcat系列—服务器安装与配置
- csu1965—Message(斯坦纳树)
- WGS84,GCJ02, BD09坐标转换
- 省赛-Fireworks
- [bzoj1492]NOI2007 CASH (DP+CDQ/Splay)
- Window下Apahce指令
- 浅谈MongoDB数据库分布式存储管理
- 简单的事情 oj61
- 为什么我们创业失败了和选择创业公司的思考
- 哈夫曼编码
- 前端开发使用css禁止选中文本,模拟双击禁止选中文本,网页禁止选中文本
- ServletContext 与application的异同
- C++网络编程(二)--客户端服务器程序