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

题意:链接

方法:cdq分治或平衡树维护凸包

解析:

这道题我拒绝写平衡树的题解,我仅仅想说splay不要写挂,insert边界条件不要忘。del点的时候不要脑抽d错。有想写平衡树的去看140142或者留言我。

首先这道题能推出个表达式

f[i]代表第i天最大收益。

xx[i]表示将第i天的钱都买A的数量

yy[i]表示将第i天的钱都买B的数量

所以f[i]=max(f[i?1],p[i].a?xx[j]+p[i].b?yy[j])j<i

所以我们要维护这个n^2的递推式

又知道f[i]是由小于i的j更新的,

但方程要进一步写一下

yy[i]=(-p[i].a/p[i].b)*xx[i]+f[i]/p[i].b

所以我们要得到最大截距所以能够依照斜率递减维护一个凸包来找某一确定直线与这个凸包截得的最大截距,也就是斜率第一个小于等于它的某个凸包上的点。

之后的部分就是採用cdq维护或者平衡树

平衡树真是一个噩梦

代码:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100010
#define eps 1e-9
#define INF 0x7fffffff
using namespace std;
typedef long long ll;
int n;
double f[N];
int stack[N];
struct node
{
    double x,y,a,b,rate,k;
    int w;
}p[N],t[N];
int cmp(node a,node b)
{
    return a.k>b.k;
}
double getk(int a,int b)
{
    if(!b)return -INF;
    if(fabs(p[a].x-p[b].x)<eps)return INF;
    return (p[b].y-p[a].y)/(p[b].x-p[a].x);
}
void solve(int l,int r)
{
    if(l==r)
    {
        f[l]=max(f[l-1],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)>>1;
    int l1=l,l2=mid+1,pt=1;
    for(int i=l;i<=r;i++)
    {
        if(p[i].w<=mid)t[l1++]=p[i];
        else t[l2++]=p[i];
    }
    for(int i=l;i<=r;i++)p[i]=t[i];
    solve(l,mid);
    int top=0;
    for(int i=l;i<=mid;i++)
    {
        while(top>1&&getk(stack[top-1],stack[top])<=getk(stack[top],i))top--;
        stack[++top]=i;
    }
    stack[++top]=0;
    for(int i=mid+1;i<=r;i++)
    {
        while(pt<top&&getk(stack[pt],stack[pt+1])>p[i].k)pt++;
        f[p[i].w]=max(f[p[i].w],p[stack[pt]].x*p[i].a+p[stack[pt]].y*p[i].b);
    }
    solve(mid+1,r);
    l1=l,l2=mid+1;
    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)t[i]=p[l1++];
       else t[i]=p[l2++];
    for(int i=l;i<=r;i++)p[i]=t[i];
}
int main()
{
    scanf("%d%lf",&n,&f[0]);
    for(int i=1;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].w=i;
    }
    sort(p+1,p+1+n,cmp);
    solve(1,n);
    printf("%.3lf\n",f[n]);
}
时间: 2024-10-13 09:17:40

BZOJ 1492 货币兑换 cdq分治或平衡树维护凸包的相关文章

bzoj-1492 货币兑换Cash (1)——平衡树维护凸包

题意: 有n天和m的初始金钱,用来购买AB两种纪念券: n天里每天都有AB的价格.每天能够进行这种操作. 1.卖出手中x%的纪念券(AB分别都卖出x%). 2.用x的金钱买入纪念券.买入AB券的比例在第i天为Rate i: 求n天过去之后所获得的最大收益. 金钱和券数均为实数: n<=100 000: 题解: 首先,尽管题中的买入和卖出都是随意数量的.可是相同的纪念券,分几天卖出得到的收 益.一定小于等于直接在一天卖出的收益: 相同.分几天买入也是不如一天花全部钱买入的: 令: f[i]为第i天

bzoj 4237: 稻草人 -- CDQ分治

4237: 稻草人 Time Limit: 40 Sec  Memory Limit: 256 MB Description JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典. 有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地.和启示中的一样,田地需要满足以下条件: 田地的形状是边平行于坐标轴的长方形: 左下角和右上角各有一个稻草人: 田地的内部(不包括边界)没有稻草人. 给出每个稻草人的坐标,请你求出有多少遵从启示的田地的个数 Input 第一

BZOJ 3262: 陌上花开 [CDQ分治 三维偏序]

Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当且仅当Sa>=Sb,Ca>=Cb,Ma>=Mb.显然,两朵花可能有同样的属性.需要统计出评出每个等级的花的数量. Input 第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值. 以下N行,每

BZOJ 2141: 排队 CDQ分治+bit

2141: 排队 Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观.设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足ihj的(i,j)数量.幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的杂乱程度.为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序

BZOJ 3262: 陌上花开 cdq分治 树状数组

https://www.lydsy.com/JudgeOnline/problem.php?id=3262 cdq分治板子题,一维排序,一维分治(cdq里的队列),一维数据结构(树状数组). 学dp优化前来复习--以前好像写过这道题但是没写博客啊--在校oj上写的题都没怎么写博客,追悔莫及 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #

BZOJ 2300 HAOI 2011 防线修建 动态维护凸包

题目大意:一些成熟分布在第一象限中,现在要建造一个防线来保护他们,但是随着时间的推移,必须要舍弃一些城市,但是不会舍弃首都.问最短的防线需要多长. 思路:在每一个时刻求一个上凸包就是答案了.当然这样做时间复杂度就呵呵了.考虑一下动态维护凸包.因为只有上凸包,所以处理起来会相对方便.我们只需把在凸包中的点按照x坐标排序,然后二分一下把点插入凸包,然后左右用斜率维护一下,这样每次插点的时间复杂度大概是O(logn).但是这样只能插点不能删点,所以离线处理一下,把删点转化为插点,最后倒着输出. (我比

[BZOJ1492] [NOI2007]货币兑换Cash 斜率优化+cdq/平衡树维护凸包

1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 5907  Solved: 2377[Submit][Status][Discuss] Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下 简称B券).每个持有金券的顾客都有一个自己的帐户.金券的数目可以是一个实数.每天随着市场的起伏波动, 两种金券都有自己当时的价值,即每一单位金

BZOJ1492 货币兑换 CDQ分治优化DP

1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec  Memory Limit: 64 MB Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下 简称B券).每个持有金券的顾客都有一个自己的帐户.金券的数目可以是一个实数.每天随着市场的起伏波动, 两种金券都有自己当时的价值,即每一单位金券当天可以兑换的人民币数目.我们记录第 K 天中 A券 和 B券 的 价值分别为 AK 和 BK(元/

hdu 4742 Pinball Game 3D(三维LIS&amp;amp;cdq分治&amp;amp;BIT维护最值)

Pinball Game 3D Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 688    Accepted Submission(s): 276 Problem Description RD is a smart boy and excel in pinball game. However, playing common 2D p