BZOJ 1492 货币兑换Cash
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的更多相关文章
- BZOJ 1492 货币兑换 Cash CDQ分治
这题n2算法就是一个维护上凸包的过程. 也可以用CDQ分治做. 我的CDQ分治做法和网上的不太一样,用左边的点建立一个凸包,右边的点在上面二分. 好处是思路清晰,避免了凸包的插入删除,坏处是多了一个l ...
- BZOJ 1492 货币兑换
Description Input 第一行两个正整数\(N,S\),分别表示小Y 能预知的天数以及初始时拥有的钱数. 接下来\(N\)行,第\(K\)行三个实数\(A_{K},B_{K},Rate_{ ...
- BZOJ 1492 [NOI2007] - cash
Description 最初你有 S 块钱, 有 N 天给你来兑换货币, 求最大获利. 一共只有两种货币 A , B . 对于每一天, 给定 3 个系数 A[i], B[i], Rate[i] A[i ...
- BZOJ 1492 货币兑换 cdq分治或平衡树维护凸包
题意:链接 方法:cdq分治或平衡树维护凸包 解析: 这道题我拒绝写平衡树的题解,我仅仅想说splay不要写挂,insert边界条件不要忘.del点的时候不要脑抽d错.有想写平衡树的去看140142或 ...
- 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】【NOI207】货币兑换Cash
DP/CDQ分治 orz Hzwer copy了下他的代码……结果在while(j<top......)这一句中把一个括号的位置打错了……找了我一个多小时才找到TAT 很神奇……顺便贴下CDQ的 ...
- bzoj千题计划237:bzoj1492: [NOI2007]货币兑换Cash
http://www.lydsy.com/JudgeOnline/problem.php?id=1492 dp[i] 表示 第i天卖完的最大收益 朴素的dp: 枚举从哪一天买来的在第i天卖掉,或者是不 ...
- 1492: [NOI2007]货币兑换Cash【CDQ分治】
1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 4166 Solved: 1736[Submit][Sta ...
- 【BZOJ-1492】货币兑换Cash DP + 斜率优化 + CDQ分治
1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 3396 Solved: 1434[Submit][Sta ...
随机推荐
- 【转】listView中,checkBox的显示和隐藏
原文网址:http://www.cnblogs.com/vicma/p/3460500.html 在listView中,每个item都有一个ChexBox,当显示的时候在listView外面设置一个按 ...
- Android调用系统相机和文件浏览器
//拍照功能,调用系统的相机功能 Intent intent2 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResul ...
- JavaScript IDE 大盘点,让选择不再难
文章来源:http://gcdn.gcpowertools.com.cn/showtopic-24110-1-3.html 阅读本文之前,分享大家一张图片,看图会发现JavaScript开发需求最 ...
- Codeforces Round #316 (Div. 2) D、E
Problem D: 题意:给定一棵n个点树,每个点有一个字母,有m个询问,每次询问某个节点x的子树中所有深度为k的点能否组成一个回文串 分析:一堆点能组成回文串当且仅当数量为奇数的字母不多于1个,显 ...
- Missing Ranges 解答
Question Given a sorted integer array where the range of elements are in the inclusive range [lower, ...
- enable ide
http://pve.proxmox.com/wiki/Migration_of_servers_to_Proxmox_VE The vmware system consists of two dis ...
- CentOS 设置mysql的远程访问
好记性不如烂笔头,记录一下. 安装了MySQL默认是拒绝远程连接的. 首先进入数据库,使用系统数据库mysql. mysql -u root -p mysql #回车,然后输入则使用了系统数据库 接着 ...
- SqlServer 自动备份、自动删除7天前备份
-----sqlserver 数据异地备份 默认删除 七天前的数据 -----该代码可配置成SQLServer作业里做调度,或者配置成任务计划进行执行 ----挂载异地盘符 exec master.. ...
- linux命令-查看当前目录下所有文件的大小:“ll -h”
//ll -h 命令只会显示文件的大小,而文件夹及其子目录或文件的大小不会显示.[root@hadoop01 soft]# ll -h total 2.1G -rw-r--r--. 1 root ro ...
- JavaScript 对象属性的遍历
ES6一共有5种方法可以遍历对象的属性. (1)for...in for...in循环遍历对象自身的和继承的可枚举属性(不含Symbol属性). (2)Object.keys(obj) Object. ...