【YBT2023寒假Day9 B】买棉花糖(DP)(分治)

买棉花糖

题目链接:YBT2023寒假Day9 B

题目大意

有 n 个商店,每个商店有 ci 个物品,原价是 ai,你在一个商店买的物品越多,下一个买的就越少,每次减少 di 块钱。
然后有 q 次询问,每次问你买 mi 个物品的最小费用。

思路

首先由一个结论,就是确定总物品数的情况下,最优情况中最多一家店选的物品数量不是 0 也不是全部。

感性的看也确实是这样,因为如果买这个越买越赚就肯定是买更多,不过还是不是那么显然,我们考虑证明:

那如果上面的条件成立,那有两家点 i,j,分别选了 x,y 个。
假设 bi,j 是在第 i 个商店买第 j 次的价格,那 bi,j=ai(j1)di
那我们首先有 bi,x>bi,x+1,bj,y>bj,y+1

那如果满足最优,那就是无论 x+1,y1x1,y+1 都不优。
那就是 bi,xbj,y+1,bj,ybi,x+1
然后联立这个式子和上面的第一个。
bj,ybi,x+1<bi,xbj,y+1
那就是 bj,y<bj,y+1,这与上面的第二个 bj,y>by,j+1 矛盾。
所以成立。

然后考虑通过看特别的那个位置在哪里,考虑分治。(fl,r,x 是第 lr 个商店里面选 x 个的代价)
那如果是 [l,mid],那你可以先左边递归下去得到 gm=fl,mid,m,然后再枚举右边 [mid+1,r],用一个背包的操作(不加或者全加),算入到 g 里面。
右边也同理,那背包一次是 O(nm) 的,总复杂度就是 O(nmlogn)

代码

#include<cstdio> #include<iostream> #define ll long long #define INF 0x3f3f3f3f3f3f3f3f using namespace std; const int N = 550; const int M = 2e4 + 100; int n, q; ll a[N], d[N], c[N], g[N << 2][M]; void slove(int now, int l, int r) { if (l == r) { for (int i = 0; i <= c[l]; i++) g[now][i] = a[l] * i - d[l] * (i - 1) * i / 2; for (int i = c[l] + 1; i <= 20000; i++) g[now][i] = INF; return ; } int mid = (l + r) >> 1; slove(now << 1, l, mid); for (int i = mid + 1; i <= r; i++) { for (int j = 20000 - c[i]; j >= 0; j--) g[now << 1][j + c[i]] = min(g[now << 1][j + c[i]], g[now << 1][j] + a[i] * c[i] - d[i] * (c[i] - 1) * c[i] / 2); } slove(now << 1 | 1, mid + 1, r); for (int i = l; i <= mid; i++) { for (int j = 20000 - c[i]; j >= 0; j--) g[now << 1 | 1][j + c[i]] = min(g[now << 1 | 1][j + c[i]], g[now << 1 | 1][j] + a[i] * c[i] - d[i] * (c[i] - 1) * c[i] / 2); } for (int i = 0; i <= 20000; i++) g[now][i] = min(g[now << 1][i], g[now << 1 | 1][i]); } int main() { freopen("marshmallow.in", "r", stdin); freopen("marshmallow.out", "w", stdout); // freopen("easy2.in", "r", stdin); // freopen("write.txt", "w", stdout); scanf("%d %d", &n, &q); for (int i = 1; i <= n; i++) { scanf("%lld %lld %lld", &a[i], &d[i], &c[i]); c[i] = min(c[i], 20000ll); } slove(1, 1, n); for (int i = 1; i <= q; i++) { int x; scanf("%d", &x); printf("%lld\n", g[1][x]); } return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/YBT2023Day9_B.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2022-02-08 【YBT2022寒假Day3 C】毒瘤染色(LCT)(圆方树)(容斥)
2022-02-08 【YBT2022寒假Day3 B】【LOJ 2460】欧拉回路 / 桥(二分)(欧拉回路)(网络流)
2022-02-08 【YBT2022寒假Day3 A】森林之和(prufer序列)(DP)
2021-02-08 GDKOI2021 爆炸记
点击右上角即可分享
微信分享提示