CF797F Mice and Holes 题解
Description
有一天 Masha 回到家,发现有
这个走廊可以用一个数轴来表示,上面有
找到让老鼠们全部都进洞的方式,使得所有老鼠运动距离总和最小。老鼠
无解输出
Solution
首先直接贪心就考虑每只老鼠选离它左边最近的或右边最近的钻,但是这样不是全局最优的。
考虑反悔贪心。
先把老鼠和洞放到一起按坐标从小到大排序,然后从前往后扫。设
如果当前枚举到了第
如果枚举到了第
至于如何处理有一个坐标有很多个洞的问题,就每次只往堆里面放一个洞,如果这个匹配了就把匹配的放进去,然后如果还有洞就再选一个没匹配的洞放进去。
时间复杂度:
Code
#include <bits/stdc++.h> #define int int64_t const int kMaxN = 1e6 + 5, kInf = 1e16; int n, m, mm; int x[kMaxN]; std::pair<int, int> h[kMaxN], a[kMaxN]; std::priority_queue<int> qm; std::priority_queue<std::pair<int, int>> qh; void dickdreamer() { std::cin >> n >> m; for (int i = 1; i <= n; ++i) { std::cin >> x[i]; a[++mm] = {x[i], 0}; } int sumc = 0; for (int i = 1; i <= m; ++i) { std::cin >> h[i].first >> h[i].second; a[++mm] = {h[i].first, i}; sumc += h[i].second; } if (sumc < n) { std::cout << "-1\n"; return; } std::sort(a + 1, a + 1 + mm); int ans = 0; for (int i = 1; i <= mm; ++i) { if (!a[i].second) { // 老鼠 int val = kInf; if (!qh.empty()) { auto [p, id] = qh.top(); qh.pop(); val = a[i].first - p; if (h[id].second) --h[id].second, qh.emplace(h[id].first, id); } ans += val; qm.emplace(a[i].first + val); } else { // 洞 int val; while (!qm.empty() && h[a[i].second].second && (val = a[i].first - qm.top()) < 0) { --h[a[i].second].second; ans += val; qm.pop(); qh.emplace(a[i].first + val, 0); } if (h[a[i].second].second) --h[a[i].second].second, qh.emplace(a[i].first, a[i].second); } } std::cout << ans << '\n'; } int32_t main() { #ifdef ORZXKR freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0); int T = 1; // std::cin >> T; while (T--) dickdreamer(); // std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n"; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步