P1485 火枪打怪 题解
新手第一次写题解 qwq
因为这道题我整整调了一整天,所以我尽可能讲的详细又简洁。
题目描述
共有 \(n\) 个怪物,血量为 \(m_i\),现在要打死这些怪物(血量 \(< 0\))。每次攻击第 \(i\) 个怪物,它会掉 \(p\) 滴血,同时左侧第 \(j\) 个怪物会掉 \(\max(0, p - (i - j) ^ 2)\) 滴血。
共使用 \(k\) 次攻击,求最小的 \(p\)。
简要分析
0x01
求一个可行的最小值,对于每一个值都是明显的是否可行。
同时因为 \(p\) 越大,\(k\) 一定会越来越小(或者维持不变),所以答案是具有单调性的。
因此可以看出,题目可以使用二分答案来做。
瞄一眼数据范围 \(10^{10}\) 好吧我直接开 long long
了。
然后就是考虑怎么设计 Check 函数了。
0x02
题目说明,当攻击怪物时,只有左侧的怪物会“收到牵连”,所以可以很快的想到,从右侧开始遍历更加方便(没有后效性)。
对于每一个怪物我们都要把它打死(因为再继续往左遍历,右面的怪物不会受到任何影响了)。
所以我们只需要考虑这个怪物会收到多大的牵连就可以了,所以我们接着从题目给的公式入手。
0x03
(\(f_i\) 为第 \(i\) 个怪物收到的溅射伤害值)
(\(cnt_i\) 为打死第 \(i\) 个怪物的最小攻击次数)
因为是倒着遍历,所以我们考虑将式子转换为一个(或多个,实际上是多个)后缀和进行运算的形式:
然后设三个后缀和数组:
然后我们就可以把原式转换为:
这样分析就结束了(但是我做了一整天[哭])
我的代码
有注释
#include <bits/stdc++.h> // 开 long long 不然会爆掉 #define int long long using namespace std; const int N = 1e6 + 10; int read() { int num = 0, flag = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') flag = -1; for (; isdigit(ch); ch = getchar()) num = (num << 3) + (num << 1) + ch - '0'; return num * flag; } int n, k; int m[N]; int c[N]; // cnt 的后缀数组 int cj[N]; // cnt * j 的后缀数组 int cjj[N]; // cnt * j * j 的后缀数组 // 获取某一个怪物背的锅的数量 int getd(int i, int j, int p) { return (p - i * i) * (c[i] - c[j]) + 2 * i * (cj[i] - cj[j]) - (cjj[i] - cjj[j]); } bool check(int p) { int x = sqrt(p), res = k; for (int i = n; i >= 1; --i) { int D = getd(i, i + x, p); // 背的锅 int cnt = (max(m[i] - D, -p) + p) / p; // 攻击次数 if ((res -= cnt) < 0) return false; // 处理后缀数组 c[i - 1] = c[i] + cnt; cj[i - 1] = cj[i] + cnt * i; cjj[i - 1] = cjj[i] + cnt * i * i; } return true; } signed main() { n = read(), k = read(); for (int i = 1; i <= n; ++i) m[i] = read(); // 二分 int l = 1, r = 1e11; while (l < r) { int mid = l + r >> 1; if (check(mid)) r = mid; else l = mid + 1; } printf("%lld\n", l); return 0; }
本文来自博客园,作者:RainPPR,转载请注明原文链接:https://www.cnblogs.com/RainPPR/p/solution-p1485.html
如有侵权请联系我(或 2125773894@qq.com)删除。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!