描述


分析

  • CDQ分治的例题, 具体怎么分析看当时的课件.
  • DP优化, 维护凸线, 斜率递增.
  • 说白了就是一个分治
  • memcpy 不比 for 循环快
  • 函数参数加引用比不加引用还慢了
  • 自己推了一遍分析过程, 放代码后面了
代码
#include #include #include using namespace std;
const int maxn = 100000 + 10;
const double INF = 1e20;
const double eps = 1e-9;
struct Node {
int id;
double a, b, r, x, y, k;
void read(int i) {
id = i;
scanf("%lf %lf %lf", &a, &b, &r);
k = -a/b;
}
bool operator < (const Node& rhs) const {
if(x < rhs.x) return 1;
return fabs(x-rhs.x) < eps && y < rhs.y;
}
} A[maxn], T[maxn];
bool cmpK(const Node& lhs, const Node& rhs) {
return lhs.k > rhs.k;
}
double getK(Node i, Node j) {
if(fabs(j.x-i.x) < eps) return INF;
return (j.y-i.y) / (j.x-i.x);
}
int S[maxn];
double f[maxn];
void solve(int L, int R)
{
if(L == R) {
f[L] = max(f[L], f[L-1]);
A[L].y = f[L] / (A[L].a * A[L].r + A[L].b);
A[L].x = A[L].y * A[L].r;
return;
}
int M = (L+R) >> 1;
int p = L, q = M+1;
for(int i = L; i <= R; i++) {
Node& x = A[i];
if(x.id <= M) T[p++] = A[i];
else T[q++] = A[i];
}
for(int i = L; i <= R; i++) A[i] = T[i];
solve(L, M);
int top = 0;
for(int i = L; i <= M; i++) {
while(top > 1 && getK(A[S[top-2]], A[S[top-1]]) - getK(A[S[top-2]], A[i]) < eps) top--;
S[top++] = i;
}
for(int i = M+1, j = 0; i <= R; i++) {
while(j < top-1 && A[i].k - getK(A[S[j]], A[S[j+1]]) < eps) j++;
Node &x = A[i], &y = A[S[j]];
f[x.id] = max(f[x.id], y.x*x.a + y.y*x.b);
}
solve(M+1, R);
p = L;
q = M+1;
for(int i = L; i <= R; i++)
if(p <= M && (A[p] < A[q] || q > R)) T[i] = A[p++];
else T[i] = A[q++];
for(int i = L; i <= R; i++) A[i] = T[i];
}
int main()
{
int n;
scanf("%d %lf", &n, &f[0]);
for(int i = 1; i <= n; i++) A[i].read(i);
sort(A+1, A+n+1, cmpK);
solve(1, n);
printf("%.3lf\n", f[n]);
}
// S的现金在Rate = r时 可以买A(B)金券a(b)单位.
a*A + b*B = S
a/b = r => b = a/r
a*A + a/r*B = S
a(A + B/r) = S
a = S*r / (A*r + B)
// 第 i 天最多获得的A金券的数量
f[i] = max{f[j] * A[j] + f[j]/r[j] * B[j], j < i} * r/(A[i]*r[i] + B[i])
j better than k :
f[j] * A[i] + f[j]/r[j] * B[i] > f[k] * A[i] + f[k]/r[k] * B[i]
f[j] * A[i] + f[j]/r[k] * B[i] - f[k] * A[i] - f[k]/r[k] * B[i] > 0
(f[j]-f[k])*A[i] + (f[j]/r[j] - f[k]/r[k])*B[i] > 0
// 发现因不知道 f[j]和f[k] 的大小关系需要分类讨论了, 不放设 f[j] < f[k]
// 设 g[x] = f[x] / r[x], g[x]的意义也很清楚, 就是第 i 天最多获得的B金券的数量
(f[j]-f[k])*A[i] + (g[j]-g[k])*B[i] > 0
(g[j]-g[k]) / (f[j]-f[k]) < -A[i]/B[i]
// 明显带有斜率的意味了, 把 f[] 看作 x, g[] 看作 y
// 那么可以看出在更新 i 的答案时, 把 i 之前的元素按 x(f[]) 从小到大排序
// 如果 j 的后面存在一个 k 使得直线 jk 的斜率不小于 -A[i]/B[i]
// 就说明 j 不优于 k
// 为判断 j 是否比后面所有点更优, 可以保存 j 之后使 jk 斜率最大的 k, 通过比较斜率判断是否可以用 j 更新 i
// 上面说的对于每个 j 都要保存一个使 jk 斜率最大的 k, 那么最后存下来点就组成一个凸线
// 凸线上从第一个点开始斜率递减, 所以更新答案要使被更新的区域 -A[i]/B[i] 递减, 因此最开始要按 -A[i]/B[i] 从大到小排序
// 来保证每一部分的 -A[i]/B[i] 都是有序的

BZOJ-1492-货币兑换cash-NOI2007-CDQ分治相关推荐

  1. 【bzoj 1492】【codevs 1797】 [NOI2007]货币兑换Cash (dp+cdq分治)

    1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 3803  Solved: 1604 [Submit][S ...

  2. BZOJ 1492 货币兑换Cash

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

  3. BZOJ - 2244 拦截导弹 (dp,CDQ分治+树状数组优化)

    BZOJ - 2244 拦截导弹 (dp,CDQ分治+树状数组优化) 1 #include<algorithm> 2 #include<iostream> 3 #include ...

  4. BZOJ 1176[Balkan2007]Mokia (cdq分治,矩阵加矩阵求和)

    BZOJ 1176[Balkan2007]Mokia (cdq分治,矩阵加矩阵求和) Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值. ...

  5. BZOJ.2716.[Violet3]天使玩偶(CDQ分治 坐标变换)

    题目链接 考虑对于两个点a,b,距离为|x[a]-x[b]|+|y[a]-y[b]|,如果a在b的右上,那我们可以把绝对值去掉,即x[a]+y[a]-(x[b]+y[b]). 即我们要求满足x[b]& ...

  6. bzoj 2244: [SDOI2011]拦截导弹 cdq分治

    2244: [SDOI2011]拦截导弹 Time Limit: 30 Sec  Memory Limit: 512 MBSec  Special Judge Submit: 237  Solved: ...

  7. 【BZOJ1492】【NOI2007】—Cash(cdq分治维护凸包优化斜率dp)

    传送门 考虑令f[i]f[i]f[i]为第iii天得到的最多的AAA券,g[i]g[i]g[i]为第iii天得到的最多的BBB券 则g[i]=f[i]/rate[i]g[i]=f[i]/rate[i] ...

  8. bzoj 2648 SJY摆棋子 cdq分治+树状数组

    题面 题目传送门 解法 同bzoj2716 自己cdq写的还是丑啊,别人A掉了我T飞了 代码 #include <bits/stdc++.h> #define inf 1 << ...

  9. BZOJ 1492: [NOI2007]货币兑换Cash [CDQ分治 斜率优化DP]

    传送门 题意:不想写... 扔链接就跑 好吧我回来了 首先发现每次兑换一定是全部兑换,因为你兑换说明有利可图,是为了后面的某一天两种卷的汇率差别明显而兑换 那么一定拿全利啊,一定比多天的组合好 $f[ ...

  10. 【BZOJ1492】[NOI2007]货币兑换Cash 斜率优化+cdq分治

    [BZOJ10492][NOI2007]货币兑换Cash Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下简称B券).每 ...

最新文章

  1. html 标签 中 的Lang 有什么用
  2. 看到数学就打怵不是你的错:百万人调查发现上黑板做题、作业太多、家长陪写都会引发焦虑|PNAS...
  3. Android seLinux 设置
  4. 变换编码(DCT)基本理解
  5. Yarn管理界面中Queue:root和Queue:default的区别
  6. UDP Socket编程 C/C++实现 (Windows Platform SDK)
  7. 我们都笑了freeeim
  8. 2K/XP/2003 系统登录密码破解
  9. 字典(JSON)与模型的转换
  10. leetcode-205-Isomorphic Strings
  11. windows安装numpy库
  12. 三菱GX Work2 PLC工控仿真
  13. 游戏测试-----------------第3章
  14. 【Excel文件合并工具】
  15. 科研工作者要会的技能----查找顶刊会议或期刊的方法
  16. Java实现经纬度格式转化
  17. Go官方的使用Gin开发Web服务教程 | Gopher Daily (2021.08.19) ʕ◔ϖ◔ʔ
  18. mysql-DTL语言
  19. NXP(Freescale) QorIQ T2080 PCIe使用
  20. Retrofit 使用

热门文章

  1. 国际会议“First Helicon Plasma Physics and Applications Worckshop”口头报告PPT
  2. [云炬学英语]每日一句2020.8.28
  3. 利用阿里云自定义镜像实现服务器数据/网站快速迁移
  4. numpy 创建加一行_数据科学|可视化图解Python科学计算包Numpy
  5. 【CyberSecurityLearning 13】简单抓包及 IP包头分析与 路由原理(一)
  6. java可视化模板——java可视化操作步骤
  7. 指针:调用自定义交换函数,完成三个数整从小到大排列
  8. 程序员面试系列——约瑟夫环
  9. C++STL理论基础
  10. DM8168心得之SD卡快速分区制作