日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ-1492-货币兑换cash-NOI2007-CDQ分治

發(fā)布時(shí)間:2025/3/15 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ-1492-货币兑换cash-NOI2007-CDQ分治 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

描述




分析

  • CDQ分治的例題, 具體怎么分析看當(dāng)時(shí)的課件.
  • DP優(yōu)化, 維護(hù)凸線, 斜率遞增.
  • 說(shuō)白了就是一個(gè)分治
  • memcpy 不比 for 循環(huán)快
  • 函數(shù)參數(shù)加引用比不加引用還慢了
  • 自己推了一遍分析過(guò)程, 放代碼后面了

代碼
#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的現(xiàn)金在Rate = r時(shí) 可以買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金券的數(shù)量 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ā)現(xiàn)因不知道 f[j]和f[k] 的大小關(guān)系需要分類討論了, 不放設(shè) f[j] < f[k]// 設(shè) g[x] = f[x] / r[x], g[x]的意義也很清楚, 就是第 i 天最多獲得的B金券的數(shù)量(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 的答案時(shí), 把 i 之前的元素按 x(f[]) 從小到大排序// 如果 j 的后面存在一個(gè) k 使得直線 jk 的斜率不小于 -A[i]/B[i]// 就說(shuō)明 j 不優(yōu)于 k// 為判斷 j 是否比后面所有點(diǎn)更優(yōu), 可以保存 j 之后使 jk 斜率最大的 k, 通過(guò)比較斜率判斷是否可以用 j 更新 i// 上面說(shuō)的對(duì)于每個(gè) j 都要保存一個(gè)使 jk 斜率最大的 k, 那么最后存下來(lái)點(diǎn)就組成一個(gè)凸線// 凸線上從第一個(gè)點(diǎn)開始斜率遞減, 所以更新答案要使被更新的區(qū)域 -A[i]/B[i] 遞減, 因此最開始要按 -A[i]/B[i] 從大到小排序// 來(lái)保證每一部分的 -A[i]/B[i] 都是有序的 與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的BZOJ-1492-货币兑换cash-NOI2007-CDQ分治的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。