CF1795E Explosions? (单调栈)
创始人
2024-05-26 05:16:56
0

传送门

题意:

有 n 个怪兽需要消灭,它们的生命值分别是 h [1],h [2]......h [n].

我们可以使用两种技能:

技能 1:选择任意一个怪兽,使其生命值降低 1 点,并且需要 1 点能量值.

技能 2:选择任意一个怪兽,使其生命值降低 x 点,需要花费 x 点能量值.

如果使用技能 2之后消灭了被选择的怪兽,那么会接着对其相邻的怪兽造成 h[ i ] - 1点伤害值. 注意:技能 2 只能使用一次!

问题:

消灭所有的怪兽最少需要花费多少能量值 ?

思路:

假设把第 i 个怪兽作为Explosion的目标,那么要求 h[1] -> h[ i ] 变成严格单调递增,h[ i ] -> h[ n ]变成严格单调递减.

我们称把 1~ i 的生命值修改为严格单调递增的代价为 L[ i ],i 到 n 的生命值修改为严格单调递减的代价是 R[ i ].

那么答案就是 min {L[ i ] + R[ i ] + h[ i ] },那么现在,问题变成了如果求出 L[ i ] 和 R[ i ].

我们只需要考虑如果求出 L[ i ]即可,因为R[ i ]可以用类似的方法求得.

考虑一个经典技术:单调栈.

做法:

单调栈:

从左到右扫一遍过去.

栈中维护一个二元组(hi,cnt)表示当前有一个怪兽血量为h[ i ],在它左边有 cnt - 1个怪兽,它们的血量从左到右单调递增且差值为 1.

栈中 h[ i ]严格单调递增.

当扫描到 i 时,实时维护一个sum,表示当前的L[ i ],如果h[ i ] > 栈顶的 h,则L[ i ] = sum,并将(hi,1)加入栈,否则,要把栈顶的(h,cnt)这cnt 个怪兽的血量全部减去 h - hi +1,才能满足条件,我们把原先的栈顶 pop.

重复这个过程,直到栈为空或者 hi > 栈顶的 h,最终,我们将(hi,cnt1)加入栈,这里的cnt1表示 1 + pop出来的cnt的和.

参考代码:

#include using LL = long long;int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);int t;std::cin >> t;while (t--) {int n;std::cin >> n;std::vector h(n);for (int i = 0; i < n; i++) {std::cin >> h[i];}std::vector L(n);std::vector R(n);for (int rot = 0; rot < 2; rot++) {std::vector> st;LL sum{};for (int i = 0; i < n; i++) {LL cnt = 1;while (!st.empty() && h[i] - cnt < st.back().first) {LL diff = st.back().first - (h[i] - cnt);sum += diff * st.back().second;cnt += st.back().second;st.pop_back();}if (cnt - 1 > h[i]) {LL extra = cnt - 1 - h[i];sum -= extra * (extra + 1) >> 1;cnt = h[i];}L[i] = sum;st.emplace_back(h[i], cnt);}std::reverse(L.begin(), L.end());std::reverse(R.begin(), R.end());std::reverse(h.begin(), h.end());std::swap(L, R);}LL ans = (LL)1e18;for (int i = 0; i < n; i++) {ans = std::min(ans, L[i] + R[i] + h[i]);}std::cout << ans << '\n';}return 0;
}

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...