bzoj-1492 货币兑换Cash (2)——CDQ分治
题意:
略
见上一篇
题解:
方程还是那个方程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分治的更多相关文章
- 【BZOJ】1492: [NOI2007]货币兑换Cash(cdq分治)
http://www.lydsy.com/JudgeOnline/problem.php?id=1492 蒟蒻来学学cdq神算法啊.. 详见论文 陈丹琦<从<Cash>谈一类分治算法 ...
- BZOJ 1492 货币兑换 Cash CDQ分治
这题n2算法就是一个维护上凸包的过程. 也可以用CDQ分治做. 我的CDQ分治做法和网上的不太一样,用左边的点建立一个凸包,右边的点在上面二分. 好处是思路清晰,避免了凸包的插入删除,坏处是多了一个l ...
- 1492: [NOI2007]货币兑换Cash【CDQ分治】
1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 4166 Solved: 1736[Submit][Sta ...
- BZOJ 1492 货币兑换Cash
http://www.lydsy.com/JudgeOnline/problem.php?id=1492 思路: 问题转变为维护一个凸包,每次转移都找凸包上的点,并更新凸壳 可以用splay维护,或者 ...
- bzoj1492 [NOI2007]货币兑换Cash【cdq分治】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1492 推荐博客:http://www.cnblogs.com/zig-zag/archive ...
- 【BZOJ1492】货币兑换Cash(CDQ分治)
题意: 小 Y 最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A 纪 念券(以下简称 A 券)和 B 纪念券(以下简称 B 券).每个持有金券的顾客都有 一个自己的帐户.金券的数目可以是一 ...
- Luogu 3810 & BZOJ 3262 陌上花开/三维偏序 | CDQ分治
Luogu 3810 & BZOJ 3263 陌上花开/三维偏序 | CDQ分治 题面 \(n\)个元素,每个元素有三个值:\(a_i\), \(b_i\) 和 \(c_i\).定义一个元素的 ...
- BZOJ 1492 货币兑换 cdq分治或平衡树维护凸包
题意:链接 方法:cdq分治或平衡树维护凸包 解析: 这道题我拒绝写平衡树的题解,我仅仅想说splay不要写挂,insert边界条件不要忘.del点的时候不要脑抽d错.有想写平衡树的去看140142或 ...
- BZOJ 1492 货币兑换
Description Input 第一行两个正整数\(N,S\),分别表示小Y 能预知的天数以及初始时拥有的钱数. 接下来\(N\)行,第\(K\)行三个实数\(A_{K},B_{K},Rate_{ ...
随机推荐
- Pollard-rho算法:模板
#include<algorithm> #include<cstdio> #include<cstdlib> #define N 5500 using namesp ...
- 五、python的练习题
1.输入一行字符,分别统计出其中英文字母.空格.数字和其他字符的个数. #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/6/5 ...
- python开发_zlib_完整版_博主推荐
''' python中的zlib模块提供了压缩和解压缩的方法 实现功能: 读取一个文件的内容,然后把该文件的内容以字符串的形式返回 然后对返回回来的字符串进行压缩处理,然后写入到另一个文件中 同时,也 ...
- BFC与hasLayout
BFC与hasLayout都是CSS布局上的概念. 几个月前在微博上才了解什么是BFC,算是对布局有点初步的了解. hasLayout则是IE6.7产生许多bug的根源. 一.BFC Floats, ...
- 【iOS开发-图层】图层的获取与一些属性
图层 每个控件都有自己的一个图层,这个空间的全部东西就是显示在这个图层上面的,控件本身没有显示东西的功能,仅仅有拥有了图层才干显示东西 图层的获取 CALayer *layer = self.test ...
- 图形图像的绘制 GandyDraw
源代码:下载地址, http://pan.baidu.com/s/1eQIzj3c 具体在下面的这个地方找,
- pytest文档4-测试用例setup和teardown
前言 学过unittest的都知道里面用前置和后置setup和teardown非常好用,在每次用例开始前和结束后都去执行一次. 当然还有更高级一点的setupClass和teardownClass,需 ...
- MERGE新特性(UPDATE WHERE,DELETE WHERE,INSERT WHERE)
MERGE语句是Oracle9i新增的语法,用来合并UPDATE和INSERT语句.通过MERGE语句,根据一张表或子查询的连接条件对另外一张表进行查询,连接条件匹配上的进行UPDATE,无法匹配的执 ...
- mysql下float类型使用一些误差详解
单精度浮点数用4字节(32bit)表示浮点数采用IEEE754标准的计算机浮点数,在内部是用二进制表示的如:7.22用32位二进制是表示不下的.所以就不精确了. mysql中float数据类型的问题总 ...
- AndroidStudio如何引入so包
转自:http://blog.csdn.net/aplixy/article/details/51592035 先说前提条件,我的AndroidStudio版本是2.2 Preview 3,版本是2. ...