470 字
2 分钟
CodeForces 2193C: C. Replace and Sum
题目链接
题目大意
给定两个长度为 的数组 和 ,以及 个区间查询。 你可以对数组 执行任意次(包括 次)以下两种操作:
- 选择一个下标 (),将 替换为 (即 ,向左传递数值);
- 选择一个下标 (),将 替换为 (即 ,从 数组获取数值)。
对于每个查询给定的区间 ,需要在允许任意次操作的前提下,使区间和最大化:
请输出每个查询对应的最大区间和。
注意:
- 操作次数不限;
- 每个查询相互独立(即回答下一个查询时,数组 视为恢复初始状态);
- 数据规模较大,需使用高效算法。
解题思路
核心性质: 的最大值只能从后面(下标 )传递过来,绝不可能从前面(下标 )获取。
具体步骤:
- 倒序遍历:从 开始向前考虑。
- 状态转移:对于位置 ,其最大值来源于当前 、对应 以及后一位 的最大值。
- 更新数组:以此类推,得到更新后的 数组(即通过若干次操作后能得到的最大值)。
- 前缀和查询:对新数组计算前缀和,即可快速响应区间查询。
代码实现
#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N=2e5+10;ll a[N], b[N], sum[N];int T, n, q, l, r;void solve(){ memset(a, 0, sizeof a); //一定要清空, 否则在a[n]=max(a[n], max(a[n+1], b[n]))的时候可能会出错,使用上一次的a[n+1] memset(sum, 0, sizeof sum); scanf("%d%d", &n, &q); for(int i=1;i<=n;i++) scanf("%lld", &a[i]); for(int i=1;i<=n;i++) scanf("%lld", &b[i]); for(int i=n;i>=1;i--) a[i]=max(a[i], max(a[i+1], b[i])); for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]; while(q--){ scanf("%d%d", &l, &r); printf("%lld ", sum[r]-sum[l-1]); printf("\n"); }}int main(){ scanf("%d", &T); while(T--) solve(); return 0;} CodeForces 2193C: C. Replace and Sum
https://shenyize.com/solutions/codeforces/2193c/