专栏文章
题解:CF2133D Chicken Jockey
CF2133D题解参与者 3已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @mio4upp8
- 此快照首次捕获于
- 2025/12/02 13:23 3 个月前
- 此快照最后确认于
- 2025/12/02 13:23 3 个月前
Solution
首先考虑最简单的情况,每次只杀栈底的怪物:
- 对于第 个怪:需要 刀。
- 对于第 个怪:在第 个怪死后,它会掉 点坠落伤害,于是就需要 刀。
此时的答案是 。
然后我们考虑提前杀掉第 只怪的收益。
- 对于第 只怪:本来需要 刀,现在需要 刀,收益为 。
- 对于第 只怪:本来需要 刀,现在需要 刀,收益为两者相减。
则净收益为 。
很自然地,我们想到 dp。但如果直接 dp 的话是有后效性的。多个位置一起提前杀,收益显然不是直接相加,而是会彼此影响。
这时候注意到一个结论:两个相邻的位置不能都被提前杀掉,否则一定不优。
证明:我们假设把 和 都提前杀掉(记作 ),证明其一定劣于只提前杀 (记作 )。
显然其只会影响到 ,我们分别来考虑。
-
对于 : 需要 刀, 现在需要 刀, 比 多打 刀。
-
对于 : 和 相同,都是 刀。
-
对于 :对于 ,由于 已经被杀掉了,所以杀 时 下面有 个怪;对于 ,杀 时 下面有 个怪。则 比 多打的刀数为 。
综上, 比 多打 或 刀,所以 劣于 。
证毕。
令 ,问题转化为:选不相邻的若干位置使得 最大。
于是就变成了简单 dp!设 表示到 为止且选/不选 的最大收益。转移是简单的。
最后答案就是 。
Code
在这
CPP// Problem: D. Chicken Jockey
// Contest: Codeforces - Codeforces Round 1044 (Div. 2)
// URL: https://codeforces.com/contest/2133/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define pii pair<int,int>
#define pb push_back
#define endl '\n'
#define rep(i, a, b) for(int (i) = (a); (i) <= (b); (i) ++)
#define per(i, a, b) for(int (i) = (a); (i) >= (b); (i) --)
#define ls x << 1
#define rs x << 1 | 1
using namespace std;
const int maxn = 2e5 + 5;
int n, h[maxn] ;
int v[maxn] ;
int f[maxn][2] ;
void solve(){
cin >> n ;
v[1] = 0 ;
rep(i, 1, n) f[i][0] = f[i][1] = 0 ;
rep(i, 1, n) cin >> h[i] ;
int base = h[1] ;
rep(i, 2, n) base += max(0ll, h[i] - 1) ;
rep(i, 2, n - 1) {
int delta = max(0ll, h[i + 1] - 1) - max(0ll, h[i + 1] - i) - 1 ;
v[i] = max(0ll, delta) ;
}
rep(i, 1, n - 1) {
f[i][0] = max(f[i - 1][0], f[i - 1][1]) ;
f[i][1] = f[i - 1][0] + v[i] ;
}
cout << base - max(f[n - 1][0], f[n - 1][1]) << endl ;
return ;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T = 1 ;
cin >> T ;
while(T -- ){
solve() ;
}
return 0 ;
}
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...