bzoj2802 [Poi2012]Warehouse Store 贪心+堆
题目传送门
https://lydsy.com/JudgeOnline/problem.php?id=2802
题解
我一开始想到了一个比较麻烦的做法。
把每一天按照 \(b_i\) 从小到大排序,\(b_i\) 小的优先选。然后扣除库存的话,优先扣除在当前这个 \(b_i\) 的位置前面最近的库存。
这个可以使用树状数组来判断能不能选,然后扣除库存的时候因为每一个日子的库存只会被扣光一次,所以可以暴力跳,但是不要走已经被扣光的点,所以使用并查集跳过这些不应该经过的点。
但是很显然这个做法很麻烦,写起来细节和码量应该都不小。
所以我们不妨换一个做法。但是我实在想不到除了我上面的做法以外还有别的什么做法。
所以去拜读了一下题解。捂脸
大概意思就是说,我们很显然会有一个非常错误的做法:对于每一位能选就选。
使这个算法错误的情况是有可能存在一个点,选了当前这个以后可能会导致后面多于一个可选方案失效。(贪心策略很多时候成立的条件是以一换一
但是不要轻易放弃这个做法!
我们想一想怎么更正这个做法。
如上文所述,使这个算法错误的情况是有可能存在一个点,选了当前这个以后可能会导致后面多于一个可选方案失效。那么我们是不是可以找出一个方法把失效方案重新变得有效呢。
既然贪心策略很多时候成立的条件是以一换一,那么我们其实可以在当前这个点不选的时候,把这个东西和目前已经选过的最大的需求量比较。如果当前这个小的话,我们其实可以把当前这个拿去替换掉之前的最大的,因为这样一定可以使剩下的总库存变大。
至于之前的最大的需求量怎么找,就是用一个堆来维护一下。
上面两个做法的时间复杂度都是 \(O(n\log n)\)。
#include<bits/stdc++.h> #define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to) #define dbg(...) fprintf(stderr, __VA_ARGS__) #define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout) #define fi first #define se second #define pb push_back template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;} template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;} typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii; template<typename I> inline void read(I &x) { int f = 0, c; while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0; x = c & 15; while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15); f ? x = -x : 0; } const int N = 250000 + 7; int n; int a[N], b[N], aa[N]; std::priority_queue<pii> q; inline void work() { ll sum = 0; int ans = 0; for (int i = 1; i <= n; ++i) { sum += a[i]; if (sum >= b[i]) sum -= b[i], q.push(pii(b[i], i)); else if (!q.empty() && sum + q.top().fi >= b[i] && b[i] <= q.top().fi) sum += q.top().fi - b[i], q.pop(), q.push(pii(b[i], i)); } while (!q.empty()) aa[++ans] = q.top().se, q.pop(); std::sort(aa + 1, aa + ans + 1); printf("%d\n", ans); for (int i = 1; i <= ans; ++i) printf("%d%c", aa[i], " \n"[i == ans]); } inline void init() { read(n); for (int i = 1; i <= n; ++i) read(a[i]); for (int i = 1; i <= n; ++i) read(b[i]); } int main() { #ifdef hzhkk freopen("hkk.in", "r", stdin); #endif init(); work(); fclose(stdin), fclose(stdout); return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 为DeepSeek添加本地知识库
· 精选4款基于.NET开源、功能强大的通讯调试工具
· DeepSeek智能编程
· 大模型工具KTransformer的安装
· [计算机/硬件/GPU] 显卡
2018-10-28 HEOI2015 兔子与樱花
2018-10-28 ZJOI2006 三色二叉树
2018-10-28 牛客网NOIP赛前集训营-提高组(第七场)C-洞穴
2018-10-28 牛客网NOIP赛前集训营-提高组(第七场)B-随机生成树
2018-10-28 牛客网NOIP赛前集训营-提高组(第七场)A-中国式家长 2