专栏文章
[002] P11642题解(幸运草)
P11642题解参与者 5已保存评论 4
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 4 条
- 当前快照
- 1 份
- 快照标识符
- @miqda0cf
- 此快照首次捕获于
- 2025/12/04 02:55 3 个月前
- 此快照最后确认于
- 2025/12/04 02:55 3 个月前
由于很难(根本不能?)确定某段区间往双向拓展后是否有对答案贡献更大的修改区间,还想不到可解的贪心。不过使用类 P1115 的新手级 dp 就能很轻松找到最好的修改区间来解决本题。
解析部分
首先构造 (即修改当前位置对答案的贡献),则要修改的区间 为 中最大子段时,即 最大。进一步地,因为答案的变化只与修改的区间有关,此时 也最大。
于是我们可以先找出 中最大的子段,本题可以考虑用简单的 dp。把 定义为 中以 结尾的最大子段和。那么由于 位置既可以承接末尾于 位置的子段并对其延长,也可以另作一段的开头。得到转移方程:
然后在转移时,需要判断一下当前位置应该属于以上两者中哪一种情况,用变量 实时更新当前最大子段的首尾,此时的 同样也是 中对答案贡献最大的修改区间 ,用前缀和维护实时求出如果修改该区间得到的答案(即原 中 , 再加上修改区间对答案的贡献: 的和),对于所有可能的 答案求出最大值。以 解决了本题。
代码部分
为了保全祖宗建议使用
CPPlong long 来实现本题。)#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,x,l,r,ans,a[100005],f[100005],b[100005],dp[100005];
signed main(){
ios::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
cin>>n>>x;
for(int i=1;i<=n;i++) cin>>a[i],f[i]=f[i-1]+a[i],b[i]=x-a[i];
ans=f[n];//需要注意不修改的特殊情况
for(int i=1;i<=n;i++){
if(dp[i-1]+b[i]>b[i]){
r=i;//事实上在过程中 r 一定等于 i
}
else l=r=i;
dp[i]=max(dp[i-1]+b[i],b[i]);
ans=max(ans,(r-l+1)*x+f[l-1]+f[n]-f[r]);
}
cout<<ans;
return 0;
}
/*
*/
相关推荐
评论
共 4 条评论,欢迎与作者交流。
正在加载评论...