[BZOJ1492][NOI2007]货币兑换Cash && CDQ分治+斜率优化
来源:互联网 发布:陈霖苍 知乎 编辑:程序博客网 时间:2024/04/28 06:28
这种分治思想我也是醉了Orz
首先对于这道题 我们可以发现 如果某一天你要买进或卖出 那一定是尽可能的买或卖
那么我们就可以用一个状态f[i]表示某一天的最大收益
那么就有 f[i] = (rate[j] * f[j] * a[i] + f[j] * b[i]) / (rate[i] * a[i] + b[i]
那么朴素转移就很容易了 怎样优化呢
令
y[j] = f[j] / (rate[i] * a[i] + b[i])
x[j] = rate[j] * f[j] / (rate[i] * a[i] + b[i]) = rate[j] * y[j];
则有 f[i] = a[i] * x[j] + b[i] * y[j];
假设决策点j 优于 决策点k 并且 j < k 当且仅当
(y[k] - y[j]) / (x[k] - x[j]) < -a[i] / b[i]
我们可以将所有 -a[i] / b[i] 从大到小排序 那么就维护一个斜率单调递减的凸包
然后就是CDQ分治了 步骤如下
1. 把区间分成两段 得到mid
2. 在原序列中小于mid的部分 进行递归
3. 当L == R 时返回答案
4. 得到答案后 维护刚刚求解部分加入后的凸包 并用他们更新mid+1到R部分的f值
5. 递归处理右子区间
话虽这么说我还是感觉很难啊QAQ
#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>#include<queue>#include<cmath>#define SF scanf#define PF printfusing namespace std;typedef long long LL;const double eps = 1e-9;const double INF = 1e20;const int MAXN = 100000;int n, sta[MAXN+10], top, S;double f[MAXN+10];struct Node { double x, y, a, b, rate, k; int id; bool operator < (const Node &t) const { return k > t.k; }} A[MAXN+10], tmp[MAXN+10];double slope(int i, int j) { if(!j) return -INF; if(fabs(A[i].x - A[j].x) < eps) return INF; return (A[j].y - A[i].y) / (A[j].x - A[i].x);}void CDQ(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].rate + A[L].b); A[L].x = A[L].rate * A[L].y; return ; } int mid = (L + R) >> 1, l1 = L, l2 = mid+1; for(int i = L; i <= R; i++) { if(A[i].id <= mid) tmp[l1++] = A[i]; else tmp[l2++] = A[i]; } for(int i = L; i <= R; i++) A[i] = tmp[i]; CDQ(L, mid); top = 0; for(int i = L; i <= mid; i++) { while(top > 1 && slope(sta[top-1], sta[top]) < slope(sta[top-1], i) + eps) top--; sta[++top] = i; } sta[++top] = 0; int j = 1; for(int i = mid+1; i <= R; i++) { while(j < top && slope(sta[j], sta[j+1]) + eps > A[i].k) j++; f[A[i].id] = max(f[A[i].id], A[sta[j]].x * A[i].a + A[sta[j]].y * A[i].b); } CDQ(mid+1, R); l1 = L; l2 = mid+1; for(int i = L; i <= R; i++) { if(l1 <= mid && (l2 > R || A[l1].x < A[l2].x || (fabs(A[l1].x - A[l2].x) < eps && A[l1].y < A[l2].y))) tmp[i] = A[l1++]; else tmp[i] = A[l2++]; } for(int i = L; i <= R; i++) A[i] = tmp[i];}int main() { SF("%d%d", &n, &S); f[0] = S; for(int i = 1; i <= n; i++) { SF("%lf%lf%lf", &A[i].a, &A[i].b, &A[i].rate); A[i].k = -A[i].a / A[i].b; A[i].id = i; } sort(A+1, A+1+n); CDQ(1, n); PF("%.3f", f[n]); return 0;}
0 0
- [BZOJ1492][NOI2007]货币兑换Cash && CDQ分治+斜率优化
- [BZOJ1492][NOI2007][CDQ分治][斜率优化][DP]货币兑换Cash
- [BZOJ1492][NOI2007]货币兑换Cash-斜率优化DP-CDQ分治
- bzoj1492 [NOI2007]货币兑换Cash(斜率优化+CDQ分治)
- [bzoj1492][cdq分治][斜率优化][NOI2007]货币兑换Cash
- bzoj1492 [NOI2007]货币兑换Cash (斜率DP+cdq分治)
- 【cdq分治】[Noi2007] bzoj1492 货币兑换Cash
- [BZOJ1492][NOI2007]货币兑换Cash(斜率优化dp+cdq分治)
- BZOJ1492:[NOI2007]货币兑换Cash (CDQ分治+斜率优化DP/平衡树维护凸壳)
- 【bzoj1492】【NOI2007】【货币兑换】【斜率优化+cdq分治】
- bzoj [NOI2007]货币兑换Cash (cdq分治+斜率优化 )
- BZOJ_P1492 [NOI2007]货币兑换Cash(CDQ分治+斜率优化)
- BZOJ1492: [NOI2007]货币兑换Cash 【dp + CDQ分治】
- CDQ分治维护凸包 优化dp 【NOI2007】货币兑换cash bzoj1492
- 【bzoj1492】[NOI2007]货币兑换Cash 斜率优化+set+凸包
- [BZOJ1492][NOI2007][斜率优化][动态凸包][DP][分治]货币兑换cash
- BZOJ1492:[NOI2007]货币兑换 (CDQ分治+斜率优化DP | splay动态维护凸包)
- NOI2007货币兑换CASH 斜率DP CDQ分治
- 各位大神对Java本质的一些的理解
- linux设备驱动第五篇:驱动中的并发与竟态
- 《unix网络编程》(16)epoll函数
- Eclipse快捷键大全
- 深入分析Java ClassLoader原理
- [BZOJ1492][NOI2007]货币兑换Cash && CDQ分治+斜率优化
- 【整理】adb命令、adb shell与Linux命令
- android studio 启动问题
- 1051. Pop Sequence (25)
- 嵌入式 详解udev
- Pie poj 二分求最大平均值
- CDilog::DoModal调用失败,原因分析
- 【NOI2007】【BZOJ1492】货币兑换Cash
- 使用cout来进行格式化输出