题意:

上一篇

题解:

方程还是那个方程f[i]=A[i] * X[j] + B[i] * Y[j]。

化简为Y[i]=(-A[i]/B[i]) * X[i] + f[i]/B[i]这一坨;

既然这个斜率不单调,那排个序让它单调不即可了;

排序之后的问题就是,在i前面更新i的点不一定能够更新i。而应该用来更新i的点说不定还在i的后面;

那么这时候就是用CDQ分治解决。

经典的四步先贴上来:

1.将操作依照时间划分为两个子区间。

2.递归处理左区间的改动与询问。

3.用左区间的改动处理右区间的询问;

4.递归处理右区间的改动与询问;

光这么四句话肯定没用,以下是详细的;

动态规划中对f[i]的更新相当于是查询,而用f[i]来更新别人则相当于是一次改动;

那么在将全部的点按斜率排序之后,进行一个分治的solve(1,n),然后按四步走;

1.划分区间:

这里的时间就是天数,仅仅须要取一个mid然后用mid把点分成两堆。

注意这里划分了以后。两个区间仍按斜率有序。而且左区间的所有时间都小于右区间的所有时间;

2.递归处理左区间:

递归下去要有一个边界,这里的边界显然就是l==r的时候;

这时这个结点前面的结点都已经对它更新了;

所以它在更新一下f[i-1]就是终于的f[i]。顺便计算出X[i]Y[i]的值;

然后每层递归结束时要按X[i]排序(为了维护凸包方便)(这种递归结构下用归并的线性显然比快拍要好);

3.用左区间改动右区间:

左区间已经按X[i]排序完毕,能够扫一遍求出凸包;

右区间如今还是按斜率排序。直接上斜率优化;

这时候右区间的全部点已经被左区间的点处理完了;

4.递归处理右区间:

被左区间处理了的点还要被右区间在它前面的点处理。所以再递归搞一下。

然后就结束了。f[n]就是答案。

这些操作全都是线性复杂度的,而一共递归有logn层。复杂度为O(nlogn);

排完序之后的下标不是时间。

。。sort写错的去看眼科大夫。

。。

代码2k+,时间1232ms;

竟然没有平衡树跑得快,可是代码上的确是省了不少。

顺便一提。bz AC50题留念(笑);

代码:

#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 110000
#define which(x) (tr[tr[x].fa].ch[1]==x)
const double INF = 1e100;
const double EPS = 1e-8;
using namespace std;
struct node
{
double x, y, slope;
int no;
}a[N], temp[N];
double f[N], A[N], B[N], R[N];
int st[N];
int cmp(node a, node b)
{
return a.slope < b.slope;
}
double slope(int x, int y)
{
if (fabs(a[x].x - a[y].x) < EPS)
return a[x].y < a[y].y ? INF : -INF;
else
return (a[x].y - a[y].y) / (a[x].x - a[y].x);
}
void merge(int l, int r)
{
memcpy(temp + l, a + l, sizeof(node)*(r - l + 1));
int mid = (l + r) >> 1, i, j, k;
for (k = l, i = l, j = mid + 1; k <= r; k++)
{
if (i <= mid&&j <= r)
a[k] = temp[i].x < temp[j].x ? temp[i++] : temp[j++];
else
a[k] = (i == mid + 1 ? temp[j++] : temp[i++]);
}
}
void slove(int l, int r)
{
if (l == r)
{
f[l] = max(f[l], f[l - 1]);
a[l].y = f[l] / (A[l] * R[l] + B[l]);
a[l].x = R[l] * a[l].y;
}
else
{
int mid = (l + r) >> 1, i, j, k, top;
for (i = l, j = l, k = mid + 1; i <= r; i++)
if (a[i].no <= mid)
temp[j++] = a[i];
else
temp[k++] = a[i];
memcpy(a + l, temp + l, sizeof(node)*(r - l + 1));
slove(l, mid);
st[top = 1] = l;
for (i = l + 1; i <= mid; i++)
{
while (top >= 2 && slope(st[top - 1], st[top]) < slope(st[top], i))
top--;
st[++top] = i;
}
for (i = mid + 1; i <= r; i++)
{
while (top >= 2 && slope(st[top - 1], st[top]) < a[i].slope)
top--;
f[a[i].no] = max(f[a[i].no], A[a[i].no] * a[st[top]].x + B[a[i].no] * a[st[top]].y);
}
slove(mid + 1, r);
merge(l, r);
}
}
int main()
{
int n, i, j, k;
double ans;
scanf("%d%lf", &n, &f[1]);
for (i = 1; i <= n; i++)
scanf("%lf%lf%lf", A + i, B + i, R + i),
a[i].slope = -A[i] / B[i],
a[i].no = i;
sort(a + 1, a + n + 1, cmp);
slove(1, n);
printf("%.3lf", f[n]);
return 0;
}

bzoj-1492 货币兑换Cash (2)——CDQ分治的更多相关文章

  1. 【BZOJ】1492: [NOI2007]货币兑换Cash(cdq分治)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1492 蒟蒻来学学cdq神算法啊.. 详见论文 陈丹琦<从<Cash>谈一类分治算法 ...

  2. BZOJ 1492 货币兑换 Cash CDQ分治

    这题n2算法就是一个维护上凸包的过程. 也可以用CDQ分治做. 我的CDQ分治做法和网上的不太一样,用左边的点建立一个凸包,右边的点在上面二分. 好处是思路清晰,避免了凸包的插入删除,坏处是多了一个l ...

  3. 1492: [NOI2007]货币兑换Cash【CDQ分治】

    1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 4166  Solved: 1736[Submit][Sta ...

  4. BZOJ 1492 货币兑换Cash

    http://www.lydsy.com/JudgeOnline/problem.php?id=1492 思路: 问题转变为维护一个凸包,每次转移都找凸包上的点,并更新凸壳 可以用splay维护,或者 ...

  5. bzoj1492 [NOI2007]货币兑换Cash【cdq分治】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1492 推荐博客:http://www.cnblogs.com/zig-zag/archive ...

  6. 【BZOJ1492】货币兑换Cash(CDQ分治)

    题意: 小 Y 最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A 纪 念券(以下简称 A 券)和 B 纪念券(以下简称 B 券).每个持有金券的顾客都有 一个自己的帐户.金券的数目可以是一 ...

  7. Luogu 3810 & BZOJ 3262 陌上花开/三维偏序 | CDQ分治

    Luogu 3810 & BZOJ 3263 陌上花开/三维偏序 | CDQ分治 题面 \(n\)个元素,每个元素有三个值:\(a_i\), \(b_i\) 和 \(c_i\).定义一个元素的 ...

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

    题意:链接 方法:cdq分治或平衡树维护凸包 解析: 这道题我拒绝写平衡树的题解,我仅仅想说splay不要写挂,insert边界条件不要忘.del点的时候不要脑抽d错.有想写平衡树的去看140142或 ...

  9. BZOJ 1492 货币兑换

    Description Input 第一行两个正整数\(N,S\),分别表示小Y 能预知的天数以及初始时拥有的钱数. 接下来\(N\)行,第\(K\)行三个实数\(A_{K},B_{K},Rate_{ ...

随机推荐

  1. 执行时间 Exercise07_16

    import java.util.Arrays; import java.util.Scanner; /** * @author 冰樱梦 * 时间:2018年下半年 * 题目:执行时间 * */ pu ...

  2. HTTP状态码,400,404,500,503

    HTTP状态码(HTTP Status Code) 一些常见的状态码为: 200 - 服务器成功返回网页 400 服务器不理解请求的语法 404 - 请求的网页不存在 503 - 服务不可用 所有状态 ...

  3. JDK源码(1.7) -- java.util.Queue<E>

    java.util.Queue<E> 源码分析(JDK1.7) -------------------------------------------------------------- ...

  4. Educational Codeforces Round 11 A. Co-prime Array 水题

    A. Co-prime Array 题目连接: http://www.codeforces.com/contest/660/problem/A Description You are given an ...

  5. mongoDB系列之(一):10分钟玩转mongoDB

    1. mongoDB是什麽 mongodb是时下流行的NoSql数据库,它的存储方式是文档式存储,并不是Key-Value形式. 存储在集合中的文档,被存储为键-值对的形式.键用于唯一标识一个文档,为 ...

  6. oc/object-c/ios用int还是NSInteger

    当需要使用int类型的变量的时候,可以像写C的程序一样,用int,也可以用NSInteger,但更推荐使用NSInteger,因为这样就不用考虑设备是32位的还是64位的. 可以看如下定义:#if _ ...

  7. CMAKE MYSQL

    http://www.blogjava.net/kelly859/archive/2012/09/04/387005.html

  8. 搭建windows server 2008 r2 FTP 后 开启防火墙无法访问的解决办法

    转自http://kkworms.blog.51cto.com/540865/558477 今天在windows server 2008 R2上安装了FTP,安装过程如下,然后添加内置防火墙设置,设置 ...

  9. openfire Hazelcast插件集群配置

    原文:http://blog.csdn.net/frankcheng5143/article/details/48708899 注意虽然hazelcast 官方已经有了3.5.2版本,但是openfi ...

  10. UIScrollView 几乎所有的属性和方法

    - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typica ...